2017-01-25 09:16:29 +01:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2017 by Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
/** \file draw_cache_impl_mesh.c
|
|
|
|
* \ingroup draw
|
2017-01-25 09:16:29 +01:00
|
|
|
*
|
|
|
|
* \brief Mesh API for render engines
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2017-02-16 16:19:48 +01:00
|
|
|
#include "BLI_math_vector.h"
|
2017-06-28 13:38:24 +10:00
|
|
|
#include "BLI_math_bits.h"
|
2017-05-01 17:58:15 +02:00
|
|
|
#include "BLI_string.h"
|
2017-06-30 18:01:20 +10:00
|
|
|
#include "BLI_alloca.h"
|
2018-05-19 13:31:44 +02:00
|
|
|
#include "BLI_edgehash.h"
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2017-05-03 18:55:40 +02:00
|
|
|
#include "DNA_object_types.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
#include "BKE_customdata.h"
|
2017-05-03 18:55:40 +02:00
|
|
|
#include "BKE_deform.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "BKE_DerivedMesh.h"
|
|
|
|
#include "BKE_editmesh.h"
|
2017-05-09 08:50:45 +10:00
|
|
|
#include "BKE_editmesh_tangent.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "BKE_mesh.h"
|
2017-05-24 22:33:21 +10:00
|
|
|
#include "BKE_mesh_tangent.h"
|
2017-12-07 23:53:03 +11:00
|
|
|
#include "BKE_colorband.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
#include "bmesh.h"
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
#include "GPU_batch.h"
|
2017-05-05 05:17:31 +10:00
|
|
|
#include "GPU_draw.h"
|
2017-06-28 13:38:24 +10:00
|
|
|
#include "GPU_material.h"
|
2018-05-19 13:31:44 +02:00
|
|
|
#include "GPU_texture.h"
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
#include "draw_cache_impl.h" /* own include */
|
|
|
|
|
|
|
|
static void mesh_batch_cache_clear(Mesh *me);
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
2017-05-05 05:07:52 +10:00
|
|
|
|
|
|
|
/** \name Mesh/BMesh Interface (direct access to basic data).
|
|
|
|
* \{ */
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
static int mesh_render_verts_len_get(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-02-23 11:54:40 +01:00
|
|
|
return me->edit_btmesh ? me->edit_btmesh->bm->totvert : me->totvert;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
static int mesh_render_edges_len_get(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-02-23 11:54:40 +01:00
|
|
|
return me->edit_btmesh ? me->edit_btmesh->bm->totedge : me->totedge;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
static int mesh_render_looptri_len_get(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-02-23 11:54:40 +01:00
|
|
|
return me->edit_btmesh ? me->edit_btmesh->tottri : poly_to_tri_count(me->totpoly, me->totloop);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
static int mesh_render_polys_len_get(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-02-23 11:54:40 +01:00
|
|
|
return me->edit_btmesh ? me->edit_btmesh->bm->totface : me->totpoly;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-05-04 23:35:50 +10:00
|
|
|
static int mesh_render_mat_len_get(Mesh *me)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
|
|
|
return MAX2(1, me->totcol);
|
|
|
|
}
|
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
static int UNUSED_FUNCTION(mesh_render_loops_len_get)(Mesh *me)
|
2017-02-16 16:19:48 +01:00
|
|
|
{
|
2017-02-23 11:54:40 +01:00
|
|
|
return me->edit_btmesh ? me->edit_btmesh->bm->totloop : me->totloop;
|
2017-02-16 16:19:48 +01:00
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
2017-05-05 05:07:52 +10:00
|
|
|
|
|
|
|
/** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
|
|
|
|
* \{ */
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
typedef struct EdgeAdjacentPolys {
|
|
|
|
int count;
|
|
|
|
int face_index[2];
|
|
|
|
} EdgeAdjacentPolys;
|
|
|
|
|
2017-04-12 14:08:44 +10:00
|
|
|
typedef struct EdgeDrawAttr {
|
|
|
|
unsigned char v_flag;
|
|
|
|
unsigned char e_flag;
|
|
|
|
unsigned char crease;
|
|
|
|
unsigned char bweight;
|
|
|
|
} EdgeDrawAttr;
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
typedef struct MeshRenderData {
|
|
|
|
int types;
|
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
int vert_len;
|
|
|
|
int edge_len;
|
|
|
|
int tri_len;
|
|
|
|
int loop_len;
|
|
|
|
int poly_len;
|
2017-05-04 23:35:50 +10:00
|
|
|
int mat_len;
|
2017-04-19 00:10:32 +10:00
|
|
|
int loose_vert_len;
|
|
|
|
int loose_edge_len;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
BMEditMesh *edit_bmesh;
|
2018-04-19 11:03:58 +02:00
|
|
|
struct EditMeshData *edit_data;
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
MVert *mvert;
|
|
|
|
MEdge *medge;
|
|
|
|
MLoop *mloop;
|
|
|
|
MPoly *mpoly;
|
2018-04-18 14:13:16 +02:00
|
|
|
float (*orco)[3]; /* vertex coordinates normalized to bounding box */
|
2018-05-30 12:40:16 +02:00
|
|
|
bool is_orco_allocated;
|
2017-05-03 18:55:40 +02:00
|
|
|
MDeformVert *dvert;
|
2017-05-22 23:31:46 +10:00
|
|
|
MLoopUV *mloopuv;
|
2017-05-22 17:21:22 +10:00
|
|
|
MLoopCol *mloopcol;
|
2017-10-31 15:15:14 -02:00
|
|
|
float (*loop_normals)[3];
|
2017-05-22 17:21:22 +10:00
|
|
|
|
|
|
|
/* CustomData 'cd' cache for efficient access. */
|
|
|
|
struct {
|
|
|
|
struct {
|
|
|
|
MLoopUV **uv;
|
|
|
|
int uv_len;
|
|
|
|
int uv_active;
|
|
|
|
|
|
|
|
MLoopCol **vcol;
|
|
|
|
int vcol_len;
|
|
|
|
int vcol_active;
|
|
|
|
|
|
|
|
float (**tangent)[4];
|
2017-06-28 09:55:40 +10:00
|
|
|
int tangent_len;
|
2017-05-22 17:21:22 +10:00
|
|
|
int tangent_active;
|
|
|
|
|
|
|
|
bool *auto_vcol;
|
|
|
|
} layers;
|
|
|
|
|
|
|
|
/* Custom-data offsets (only needed for BMesh access) */
|
|
|
|
struct {
|
|
|
|
int crease;
|
|
|
|
int bweight;
|
|
|
|
int *uv;
|
|
|
|
int *vcol;
|
|
|
|
} offset;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
char (*auto_mix)[32];
|
|
|
|
char (*uv)[32];
|
|
|
|
char (*vcol)[32];
|
|
|
|
char (*tangent)[32];
|
|
|
|
} uuid;
|
|
|
|
|
|
|
|
/* for certain cases we need an output loop-data storage (bmesh tangents) */
|
|
|
|
struct {
|
|
|
|
CustomData ldata;
|
|
|
|
/* grr, special case variable (use in place of 'dm->tangent_mask') */
|
2017-07-03 19:49:35 +03:00
|
|
|
short tangent_mask;
|
2017-05-22 17:21:22 +10:00
|
|
|
} output;
|
|
|
|
} cd;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-02-26 21:07:37 +01:00
|
|
|
BMVert *eve_act;
|
|
|
|
BMEdge *eed_act;
|
|
|
|
BMFace *efa_act;
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
/* Data created on-demand (usually not for bmesh-based data). */
|
|
|
|
EdgeAdjacentPolys *edges_adjacent_polys;
|
|
|
|
MLoopTri *mlooptri;
|
2017-02-28 14:30:34 +01:00
|
|
|
int *loose_edges;
|
|
|
|
int *loose_verts;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
float (*poly_normals)[3];
|
2017-05-04 19:59:27 +02:00
|
|
|
float (*vert_weight_color)[3];
|
|
|
|
char (*vert_color)[3];
|
2017-06-29 20:11:16 +10:00
|
|
|
Gwn_PackedNormal *poly_normals_pack;
|
|
|
|
Gwn_PackedNormal *vert_normals_pack;
|
2017-05-17 11:46:26 +10:00
|
|
|
bool *edge_select_bool;
|
2017-02-23 11:54:40 +01:00
|
|
|
} MeshRenderData;
|
|
|
|
|
|
|
|
enum {
|
2017-02-28 14:30:34 +01:00
|
|
|
MR_DATATYPE_VERT = 1 << 0,
|
2017-03-01 14:07:04 +01:00
|
|
|
MR_DATATYPE_EDGE = 1 << 1,
|
|
|
|
MR_DATATYPE_LOOPTRI = 1 << 2,
|
|
|
|
MR_DATATYPE_LOOP = 1 << 3,
|
|
|
|
MR_DATATYPE_POLY = 1 << 4,
|
|
|
|
MR_DATATYPE_OVERLAY = 1 << 5,
|
2017-05-01 17:58:15 +02:00
|
|
|
MR_DATATYPE_SHADING = 1 << 6,
|
2017-05-03 18:55:40 +02:00
|
|
|
MR_DATATYPE_DVERT = 1 << 7,
|
2017-05-04 19:59:27 +02:00
|
|
|
MR_DATATYPE_LOOPCOL = 1 << 8,
|
2017-05-22 23:31:46 +10:00
|
|
|
MR_DATATYPE_LOOPUV = 1 << 9,
|
2017-02-23 11:54:40 +01:00
|
|
|
};
|
|
|
|
|
2017-04-18 23:29:55 +10:00
|
|
|
/**
|
|
|
|
* These functions look like they would be slow but they will typically return true on the first iteration.
|
|
|
|
* Only false when all attached elements are hidden.
|
|
|
|
*/
|
|
|
|
static bool bm_vert_has_visible_edge(const BMVert *v)
|
|
|
|
{
|
|
|
|
const BMEdge *e_iter, *e_first;
|
|
|
|
|
|
|
|
e_iter = e_first = v->e;
|
|
|
|
do {
|
|
|
|
if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool bm_edge_has_visible_face(const BMEdge *e)
|
|
|
|
{
|
|
|
|
const BMLoop *l_iter, *l_first;
|
|
|
|
l_iter = l_first = e->l;
|
|
|
|
do {
|
|
|
|
if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} while ((l_iter = l_iter->radial_next) != l_first);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
static void mesh_cd_calc_used_gpu_layers(
|
|
|
|
CustomData *UNUSED(cd_vdata), uchar cd_vused[CD_NUMTYPES],
|
2017-07-04 16:03:04 +03:00
|
|
|
CustomData *cd_ldata, ushort cd_lused[CD_NUMTYPES],
|
2017-06-28 13:38:24 +10:00
|
|
|
struct GPUMaterial **gpumat_array, int gpumat_array_len)
|
|
|
|
{
|
2017-06-29 15:23:47 +10:00
|
|
|
/* See: DM_vertex_attributes_from_gpu for similar logic */
|
2017-08-12 14:07:37 +02:00
|
|
|
GPUVertexAttribs gattribs = {{{0}}};
|
2017-06-28 13:38:24 +10:00
|
|
|
|
|
|
|
for (int i = 0; i < gpumat_array_len; i++) {
|
|
|
|
GPUMaterial *gpumat = gpumat_array[i];
|
|
|
|
if (gpumat) {
|
|
|
|
GPU_material_vertex_attributes(gpumat, &gattribs);
|
|
|
|
for (int j = 0; j < gattribs.totlayer; j++) {
|
|
|
|
const char *name = gattribs.layer[j].name;
|
2017-06-29 15:23:47 +10:00
|
|
|
int type = gattribs.layer[j].type;
|
|
|
|
int layer = -1;
|
|
|
|
|
|
|
|
if (type == CD_AUTO_FROM_NAME) {
|
|
|
|
/* We need to deduct what exact layer is used.
|
|
|
|
*
|
|
|
|
* We do it based on the specified name.
|
|
|
|
*/
|
2017-07-03 12:46:58 +02:00
|
|
|
if (name[0] != '\0') {
|
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name);
|
2017-06-29 15:23:47 +10:00
|
|
|
type = CD_MTFACE;
|
2017-07-03 12:46:58 +02:00
|
|
|
|
2017-06-29 15:23:47 +10:00
|
|
|
if (layer == -1) {
|
2017-07-03 12:46:58 +02:00
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
|
2017-06-29 15:23:47 +10:00
|
|
|
type = CD_MCOL;
|
|
|
|
}
|
|
|
|
#if 0 /* Tangents are always from UV's - this will never happen. */
|
|
|
|
if (layer == -1) {
|
2017-07-03 12:46:58 +02:00
|
|
|
layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name);
|
2017-06-29 15:23:47 +10:00
|
|
|
type = CD_TANGENT;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (layer == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Fall back to the UV layer, which matches old behavior. */
|
|
|
|
type = CD_MTFACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
2017-06-28 13:38:24 +10:00
|
|
|
case CD_MTFACE:
|
|
|
|
{
|
2017-06-29 15:23:47 +10:00
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ?
|
|
|
|
CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
|
|
|
|
CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
|
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_lused[CD_MLOOPUV] |= (1 << layer);
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CD_TANGENT:
|
|
|
|
{
|
2017-06-29 15:23:47 +10:00
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ?
|
|
|
|
CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
|
|
|
|
CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
|
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_lused[CD_TANGENT] |= (1 << layer);
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
2017-07-04 16:03:04 +03:00
|
|
|
else {
|
|
|
|
/* no UV layers at all => requesting orco */
|
|
|
|
cd_lused[CD_TANGENT] |= DM_TANGENT_MASK_ORCO;
|
|
|
|
cd_vused[CD_ORCO] |= 1;
|
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CD_MCOL:
|
|
|
|
{
|
2017-06-29 15:23:47 +10:00
|
|
|
if (layer == -1) {
|
|
|
|
layer = (name[0] != '\0') ?
|
|
|
|
CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
|
|
|
|
CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
|
|
|
|
}
|
|
|
|
if (layer != -1) {
|
|
|
|
cd_lused[CD_MLOOPCOL] |= (1 << layer);
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CD_ORCO:
|
|
|
|
{
|
|
|
|
cd_vused[CD_ORCO] |= 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-06 14:14:07 -02:00
|
|
|
|
|
|
|
static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float split_angle, MeshRenderData *rdata)
|
|
|
|
{
|
|
|
|
BLI_assert((me->flag & ME_AUTOSMOOTH) != 0);
|
|
|
|
|
|
|
|
int totloop = me->totloop;
|
|
|
|
int totpoly = me->totpoly;
|
|
|
|
float (*loop_normals)[3] = MEM_mallocN(sizeof(*loop_normals) * totloop, __func__);
|
|
|
|
float (*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
|
|
|
|
short (*clnors)[2] = CustomData_get_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
|
|
|
|
|
|
|
|
BKE_mesh_calc_normals_poly(
|
|
|
|
me->mvert, NULL, me->totvert,
|
|
|
|
me->mloop, me->mpoly, totloop, totpoly, poly_normals, false);
|
|
|
|
|
|
|
|
BKE_mesh_normals_loop_split(
|
|
|
|
me->mvert, me->totvert, me->medge, me->totedge,
|
|
|
|
me->mloop, loop_normals, totloop, me->mpoly, poly_normals, totpoly,
|
|
|
|
true, split_angle, NULL, clnors, NULL);
|
|
|
|
|
|
|
|
rdata->loop_len = totloop;
|
|
|
|
rdata->poly_len = totpoly;
|
|
|
|
rdata->loop_normals = loop_normals;
|
|
|
|
rdata->poly_normals = poly_normals;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
/**
|
|
|
|
* TODO(campbell): 'gpumat_array' may include materials linked to the object.
|
|
|
|
* While not default, object materials should be supported.
|
|
|
|
* Although this only impacts the data thats generated, not the materials that display.
|
|
|
|
*/
|
|
|
|
static MeshRenderData *mesh_render_data_create_ex(
|
|
|
|
Mesh *me, const int types,
|
|
|
|
struct GPUMaterial **gpumat_array, uint gpumat_array_len)
|
2017-02-23 11:54:40 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
|
|
|
|
rdata->types = types;
|
2017-05-04 23:35:50 +10:00
|
|
|
rdata->mat_len = mesh_render_mat_len_get(me);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
CustomData_reset(&rdata->cd.output.ldata);
|
2017-05-09 08:50:45 +10:00
|
|
|
|
2017-11-06 14:14:07 -02:00
|
|
|
const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
|
|
|
|
const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
if (me->edit_btmesh) {
|
|
|
|
BMEditMesh *embm = me->edit_btmesh;
|
|
|
|
BMesh *bm = embm->bm;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->edit_bmesh = embm;
|
2018-05-02 15:47:45 +02:00
|
|
|
rdata->edit_data = me->runtime.edit_data;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
int bm_ensure_types = 0;
|
2018-05-15 08:56:45 +02:00
|
|
|
if (types & MR_DATATYPE_VERT) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->vert_len = bm->totvert;
|
2017-02-23 11:54:40 +01:00
|
|
|
bm_ensure_types |= BM_VERT;
|
|
|
|
}
|
2018-05-15 08:56:45 +02:00
|
|
|
if (types & MR_DATATYPE_EDGE) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->edge_len = bm->totedge;
|
2017-02-23 11:54:40 +01:00
|
|
|
bm_ensure_types |= BM_EDGE;
|
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_LOOPTRI) {
|
|
|
|
BKE_editmesh_tessface_calc(embm);
|
2018-05-15 08:56:45 +02:00
|
|
|
int tottri = embm->tottri;
|
|
|
|
rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * embm->tottri, __func__);
|
|
|
|
for (int index = 0; index < tottri ; index ++ ) {
|
|
|
|
BMLoop **bmtri = embm->looptris[index];
|
|
|
|
MLoopTri *mtri = &rdata->mlooptri[index];
|
|
|
|
mtri->tri[0] = BM_elem_index_get(bmtri[0]);
|
|
|
|
mtri->tri[1] = BM_elem_index_get(bmtri[1]);
|
|
|
|
mtri->tri[2] = BM_elem_index_get(bmtri[2]);
|
|
|
|
}
|
|
|
|
rdata->tri_len = tottri;
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_LOOP) {
|
2017-11-06 14:14:07 -02:00
|
|
|
int totloop = bm->totloop;
|
|
|
|
if (is_auto_smooth) {
|
|
|
|
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__);
|
|
|
|
BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
|
|
|
|
}
|
|
|
|
rdata->loop_len = totloop;
|
2017-02-23 11:54:40 +01:00
|
|
|
bm_ensure_types |= BM_LOOP;
|
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_POLY) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->poly_len = bm->totface;
|
2017-02-23 11:54:40 +01:00
|
|
|
bm_ensure_types |= BM_FACE;
|
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
if (types & MR_DATATYPE_OVERLAY) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->efa_act = BM_mesh_active_face_get(bm, false, true);
|
|
|
|
rdata->eed_act = BM_mesh_active_edge_get(bm);
|
|
|
|
rdata->eve_act = BM_mesh_active_vert_get(bm);
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->cd.offset.crease = CustomData_get_offset(&bm->edata, CD_CREASE);
|
|
|
|
rdata->cd.offset.bweight = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
|
2017-02-26 21:07:37 +01:00
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
if (types & (MR_DATATYPE_DVERT)) {
|
|
|
|
bm_ensure_types |= BM_VERT;
|
|
|
|
}
|
2018-04-19 11:03:58 +02:00
|
|
|
if (rdata->edit_data != NULL) {
|
|
|
|
bm_ensure_types |= BM_VERT;
|
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
BM_mesh_elem_index_ensure(bm, bm_ensure_types);
|
|
|
|
BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP);
|
2017-03-01 14:07:04 +01:00
|
|
|
if (types & MR_DATATYPE_OVERLAY) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->loose_vert_len = rdata->loose_edge_len = 0;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
int *lverts = rdata->loose_verts = MEM_mallocN(rdata->vert_len * sizeof(int), "Loose Vert");
|
|
|
|
int *ledges = rdata->loose_edges = MEM_mallocN(rdata->edge_len * sizeof(int), "Loose Edges");
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-04-12 15:42:41 +10:00
|
|
|
{
|
|
|
|
BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
|
|
|
|
BMVert **vtable = bm->vtable;
|
|
|
|
for (int i = 0; i < bm->totvert; i++) {
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMVert *eve = vtable[i];
|
|
|
|
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
2017-04-18 23:29:55 +10:00
|
|
|
/* Loose vert */
|
2017-05-24 13:33:48 +10:00
|
|
|
if (eve->e == NULL || !bm_vert_has_visible_edge(eve)) {
|
2017-04-20 16:24:35 +10:00
|
|
|
lverts[rdata->loose_vert_len++] = i;
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-04-12 15:42:41 +10:00
|
|
|
}
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
2017-04-12 15:42:41 +10:00
|
|
|
}
|
2017-02-28 14:30:34 +01:00
|
|
|
|
2017-04-12 15:42:41 +10:00
|
|
|
{
|
|
|
|
BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
|
|
|
|
BMEdge **etable = bm->etable;
|
|
|
|
for (int i = 0; i < bm->totedge; i++) {
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMEdge *eed = etable[i];
|
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
2017-04-18 23:29:55 +10:00
|
|
|
/* Loose edge */
|
2017-05-24 13:33:48 +10:00
|
|
|
if (eed->l == NULL || !bm_edge_has_visible_face(eed)) {
|
2017-04-20 16:24:35 +10:00
|
|
|
ledges[rdata->loose_edge_len++] = i;
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
2017-04-12 15:42:41 +10:00
|
|
|
}
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
2017-04-12 15:42:41 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->loose_verts = MEM_reallocN(rdata->loose_verts, rdata->loose_vert_len * sizeof(int));
|
|
|
|
rdata->loose_edges = MEM_reallocN(rdata->loose_edges, rdata->loose_edge_len * sizeof(int));
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-03-01 14:07:04 +01:00
|
|
|
if (types & (MR_DATATYPE_VERT)) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->vert_len = me->totvert;
|
|
|
|
rdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
if (types & (MR_DATATYPE_EDGE)) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->edge_len = me->totedge;
|
|
|
|
rdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_LOOPTRI) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const int tri_len = rdata->tri_len = poly_to_tri_count(me->totpoly, me->totloop);
|
|
|
|
rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * tri_len, __func__);
|
|
|
|
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_LOOP) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->loop_len = me->totloop;
|
|
|
|
rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
|
2017-11-06 14:14:07 -02:00
|
|
|
|
|
|
|
if (is_auto_smooth) {
|
|
|
|
mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
|
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
if (types & MR_DATATYPE_POLY) {
|
2017-04-20 16:24:35 +10:00
|
|
|
rdata->poly_len = me->totpoly;
|
|
|
|
rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
if (types & MR_DATATYPE_DVERT) {
|
|
|
|
rdata->vert_len = me->totvert;
|
|
|
|
rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
|
|
|
|
}
|
2017-05-04 19:59:27 +02:00
|
|
|
if (types & MR_DATATYPE_LOOPCOL) {
|
|
|
|
rdata->loop_len = me->totloop;
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
|
2017-05-04 19:59:27 +02:00
|
|
|
}
|
2017-05-22 23:31:46 +10:00
|
|
|
if (types & MR_DATATYPE_LOOPUV) {
|
|
|
|
rdata->loop_len = me->totloop;
|
|
|
|
rdata->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-05-01 17:58:15 +02:00
|
|
|
if (types & MR_DATATYPE_SHADING) {
|
2017-05-09 08:50:45 +10:00
|
|
|
CustomData *cd_vdata, *cd_ldata;
|
|
|
|
|
|
|
|
if (me->edit_btmesh) {
|
|
|
|
BMesh *bm = me->edit_btmesh->bm;
|
|
|
|
cd_vdata = &bm->vdata;
|
|
|
|
cd_ldata = &bm->ldata;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cd_vdata = &me->vdata;
|
|
|
|
cd_ldata = &me->ldata;
|
|
|
|
}
|
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
/* Add edge/poly if we need them */
|
|
|
|
uchar cd_vused[CD_NUMTYPES] = {0};
|
2017-07-04 16:03:04 +03:00
|
|
|
ushort cd_lused[CD_NUMTYPES] = {0};
|
2017-06-28 13:38:24 +10:00
|
|
|
|
|
|
|
mesh_cd_calc_used_gpu_layers(
|
|
|
|
cd_vdata, cd_vused,
|
|
|
|
cd_ldata, cd_lused,
|
|
|
|
gpumat_array, gpumat_array_len);
|
|
|
|
|
2017-06-28 09:55:40 +10:00
|
|
|
|
|
|
|
rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
|
|
|
|
rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
|
|
|
|
rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
|
|
|
|
|
2017-06-29 15:34:50 +10:00
|
|
|
#define CD_VALIDATE_ACTIVE_LAYER(active_index, used) \
|
|
|
|
if ((active_index != -1) && (used & (1 << active_index)) == 0) { \
|
|
|
|
active_index = -1; \
|
|
|
|
} ((void)0)
|
|
|
|
|
|
|
|
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_active, cd_lused[CD_MLOOPUV]);
|
|
|
|
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_active, cd_lused[CD_TANGENT]);
|
|
|
|
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_active, cd_lused[CD_MLOOPCOL]);
|
|
|
|
|
|
|
|
#undef CD_VALIDATE_ACTIVE_LAYER
|
2017-06-28 13:38:24 +10:00
|
|
|
|
2018-05-30 12:40:16 +02:00
|
|
|
rdata->is_orco_allocated = false;
|
2017-06-28 13:38:24 +10:00
|
|
|
if (cd_vused[CD_ORCO] & 1) {
|
|
|
|
rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
|
|
|
|
/* If orco is not available compute it ourselves */
|
|
|
|
if (!rdata->orco) {
|
2018-05-30 12:40:16 +02:00
|
|
|
rdata->is_orco_allocated = true;
|
2017-06-28 13:38:24 +10:00
|
|
|
if (me->edit_btmesh) {
|
|
|
|
BMesh *bm = me->edit_btmesh->bm;
|
|
|
|
rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
|
|
|
|
BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
|
|
|
|
BMVert **vtable = bm->vtable;
|
|
|
|
for (int i = 0; i < bm->totvert; i++) {
|
|
|
|
copy_v3_v3(rdata->orco[i], vtable[i]->co);
|
|
|
|
}
|
|
|
|
BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
|
2017-05-09 08:50:45 +10:00
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
else {
|
|
|
|
rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
|
|
|
|
MVert *mvert = rdata->mvert;
|
|
|
|
for (int a = 0; a < rdata->vert_len; a++, mvert++) {
|
|
|
|
copy_v3_v3(rdata->orco[a], mvert->co);
|
|
|
|
}
|
|
|
|
BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
|
2017-05-09 08:50:45 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
else {
|
|
|
|
rdata->orco = NULL;
|
|
|
|
}
|
2017-05-09 08:50:45 +10:00
|
|
|
|
|
|
|
/* don't access mesh directly, instead use vars taken from BMesh or Mesh */
|
|
|
|
#define me DONT_USE_THIS
|
2017-05-21 09:39:31 +10:00
|
|
|
#ifdef me /* quiet warning */
|
|
|
|
#endif
|
2017-06-28 13:38:24 +10:00
|
|
|
struct {
|
|
|
|
uint uv_len;
|
|
|
|
uint vcol_len;
|
|
|
|
} cd_layers_src = {
|
|
|
|
.uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV),
|
|
|
|
.vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL),
|
|
|
|
};
|
2017-05-09 08:50:45 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
rdata->cd.layers.uv_len = count_bits_i(cd_lused[CD_MLOOPUV]);
|
|
|
|
rdata->cd.layers.tangent_len = count_bits_i(cd_lused[CD_TANGENT]);
|
|
|
|
rdata->cd.layers.vcol_len = count_bits_i(cd_lused[CD_MLOOPCOL]);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->cd.layers.uv = MEM_mallocN(sizeof(*rdata->cd.layers.uv) * rdata->cd.layers.uv_len, __func__);
|
|
|
|
rdata->cd.layers.vcol = MEM_mallocN(sizeof(*rdata->cd.layers.vcol) * rdata->cd.layers.vcol_len, __func__);
|
2017-06-28 13:38:24 +10:00
|
|
|
rdata->cd.layers.tangent = MEM_mallocN(sizeof(*rdata->cd.layers.tangent) * rdata->cd.layers.tangent_len, __func__);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->cd.uuid.uv = MEM_mallocN(sizeof(*rdata->cd.uuid.uv) * rdata->cd.layers.uv_len, __func__);
|
|
|
|
rdata->cd.uuid.vcol = MEM_mallocN(sizeof(*rdata->cd.uuid.vcol) * rdata->cd.layers.vcol_len, __func__);
|
2017-06-28 13:38:24 +10:00
|
|
|
rdata->cd.uuid.tangent = MEM_mallocN(sizeof(*rdata->cd.uuid.tangent) * rdata->cd.layers.tangent_len, __func__);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->cd.offset.uv = MEM_mallocN(sizeof(*rdata->cd.offset.uv) * rdata->cd.layers.uv_len, __func__);
|
|
|
|
rdata->cd.offset.vcol = MEM_mallocN(sizeof(*rdata->cd.offset.vcol) * rdata->cd.layers.vcol_len, __func__);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
|
|
|
/* Allocate max */
|
2017-05-22 17:21:22 +10:00
|
|
|
rdata->cd.layers.auto_vcol = MEM_callocN(
|
|
|
|
sizeof(*rdata->cd.layers.auto_vcol) * rdata->cd.layers.vcol_len, __func__);
|
|
|
|
rdata->cd.uuid.auto_mix = MEM_mallocN(
|
|
|
|
sizeof(*rdata->cd.uuid.auto_mix) * (rdata->cd.layers.vcol_len + rdata->cd.layers.uv_len), __func__);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
|
|
|
/* XXX FIXME XXX */
|
|
|
|
/* We use a hash to identify each data layer based on its name.
|
|
|
|
* Gawain then search for this name in the current shader and bind if it exists.
|
|
|
|
* NOTE : This is prone to hash collision.
|
|
|
|
* One solution to hash collision would be to format the cd layer name
|
|
|
|
* to a safe glsl var name, but without name clash.
|
|
|
|
* NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */
|
2017-06-28 13:38:24 +10:00
|
|
|
if (rdata->cd.layers.vcol_len != 0) {
|
|
|
|
for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.vcol_len; i_src++, i_dst++) {
|
|
|
|
if ((cd_lused[CD_MLOOPCOL] & (1 << i_src)) == 0) {
|
|
|
|
i_dst--;
|
|
|
|
if (rdata->cd.layers.vcol_active >= i_src) {
|
|
|
|
rdata->cd.layers.vcol_active--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i_src);
|
2018-05-11 07:48:52 +02:00
|
|
|
uint hash = BLI_ghashutil_strhash_p(name);
|
2017-06-28 13:38:24 +10:00
|
|
|
BLI_snprintf(rdata->cd.uuid.vcol[i_dst], sizeof(*rdata->cd.uuid.vcol), "c%u", hash);
|
|
|
|
rdata->cd.layers.vcol[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i_src);
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
rdata->cd.offset.vcol[i_dst] = CustomData_get_n_offset(
|
|
|
|
&rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i_src);
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
/* Gather number of auto layers. */
|
|
|
|
/* We only do vcols that are not overridden by uvs */
|
|
|
|
if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) {
|
|
|
|
BLI_snprintf(
|
|
|
|
rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + i_dst],
|
|
|
|
sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
|
|
|
|
rdata->cd.layers.auto_vcol[i_dst] = true;
|
|
|
|
}
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start Fresh */
|
2017-06-28 13:38:24 +10:00
|
|
|
CustomData_free_layers(cd_ldata, CD_TANGENT, rdata->loop_len);
|
2017-05-09 08:50:45 +10:00
|
|
|
CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
if (rdata->cd.layers.uv_len != 0) {
|
|
|
|
for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
|
|
|
|
if ((cd_lused[CD_MLOOPUV] & (1 << i_src)) == 0) {
|
|
|
|
i_dst--;
|
|
|
|
if (rdata->cd.layers.uv_active >= i_src) {
|
|
|
|
rdata->cd.layers.uv_active--;
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
else {
|
|
|
|
const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
|
2018-05-11 07:48:52 +02:00
|
|
|
uint hash = BLI_ghashutil_strhash_p(name);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
BLI_snprintf(rdata->cd.uuid.uv[i_dst], sizeof(*rdata->cd.uuid.uv), "u%u", hash);
|
|
|
|
rdata->cd.layers.uv[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i_src);
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
rdata->cd.offset.uv[i_dst] = CustomData_get_n_offset(
|
|
|
|
&rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i_src);
|
2017-05-24 22:47:18 +10:00
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
BLI_snprintf(rdata->cd.uuid.auto_mix[i_dst], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-24 22:47:18 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
if (rdata->cd.layers.tangent_len != 0) {
|
2017-05-09 08:50:45 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Pre-calculate tangents into 'rdata->cd.output.ldata' */
|
2017-05-25 02:31:39 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
BLI_assert(!CustomData_has_layer(&rdata->cd.output.ldata, CD_TANGENT));
|
|
|
|
|
|
|
|
/* Tangent Names */
|
|
|
|
char tangent_names[MAX_MTFACE][MAX_NAME];
|
|
|
|
for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
|
|
|
|
if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
|
|
|
|
i_dst--;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_strncpy(
|
|
|
|
tangent_names[i_dst],
|
|
|
|
CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src), MAX_NAME);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-04 16:03:04 +03:00
|
|
|
/* If tangent from orco is requested, decrement tangent_len */
|
|
|
|
int actual_tangent_len = (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) ?
|
2017-10-07 15:57:14 +11:00
|
|
|
rdata->cd.layers.tangent_len - 1 : rdata->cd.layers.tangent_len;
|
2017-06-28 13:38:24 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMEditMesh *em = rdata->edit_bmesh;
|
|
|
|
BMesh *bm = em->bm;
|
|
|
|
|
2017-10-31 15:15:14 -02:00
|
|
|
if (is_auto_smooth && rdata->loop_normals == NULL) {
|
2017-11-06 14:14:07 -02:00
|
|
|
/* Should we store the previous array of `loop_normals` in somewhere? */
|
|
|
|
rdata->loop_len = bm->totloop;
|
|
|
|
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__);
|
|
|
|
BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
bool calc_active_tangent = false;
|
|
|
|
|
|
|
|
BKE_editmesh_loop_tangent_calc(
|
|
|
|
em, calc_active_tangent,
|
2017-07-04 16:03:04 +03:00
|
|
|
tangent_names, actual_tangent_len,
|
2017-10-31 15:15:14 -02:00
|
|
|
rdata->poly_normals, rdata->loop_normals,
|
2017-06-28 13:38:24 +10:00
|
|
|
rdata->orco,
|
|
|
|
&rdata->cd.output.ldata, bm->totloop,
|
|
|
|
&rdata->cd.output.tangent_mask);
|
|
|
|
}
|
|
|
|
else {
|
2017-05-09 08:50:45 +10:00
|
|
|
#undef me
|
2017-05-25 02:31:39 +10:00
|
|
|
|
2017-10-31 15:15:14 -02:00
|
|
|
if (is_auto_smooth && rdata->loop_normals == NULL) {
|
2017-11-06 14:14:07 -02:00
|
|
|
/* Should we store the previous array of `loop_normals` in CustomData? */
|
|
|
|
mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
2017-05-24 22:33:21 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
bool calc_active_tangent = false;
|
|
|
|
|
|
|
|
BKE_mesh_calc_loop_tangent_ex(
|
|
|
|
me->mvert,
|
|
|
|
me->mpoly, me->totpoly,
|
|
|
|
me->mloop,
|
|
|
|
rdata->mlooptri, rdata->tri_len,
|
|
|
|
cd_ldata,
|
|
|
|
calc_active_tangent,
|
2017-07-04 16:03:04 +03:00
|
|
|
tangent_names, actual_tangent_len,
|
2017-10-31 15:15:14 -02:00
|
|
|
rdata->poly_normals, rdata->loop_normals,
|
2017-06-28 13:38:24 +10:00
|
|
|
rdata->orco,
|
|
|
|
&rdata->cd.output.ldata, me->totloop,
|
|
|
|
&rdata->cd.output.tangent_mask);
|
|
|
|
|
|
|
|
/* If we store tangents in the mesh, set temporary. */
|
2017-05-24 22:33:21 +10:00
|
|
|
#if 0
|
2017-06-28 13:38:24 +10:00
|
|
|
CustomData_set_layer_flag(cd_ldata, CD_TANGENT, CD_FLAG_TEMPORARY);
|
2017-05-24 22:33:21 +10:00
|
|
|
#endif
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-05-09 08:50:45 +10:00
|
|
|
#define me DONT_USE_THIS
|
2017-05-21 09:39:31 +10:00
|
|
|
#ifdef me /* quiet warning */
|
|
|
|
#endif
|
2017-06-28 13:38:24 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/* End tangent calculation */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
BLI_assert(CustomData_number_of_layers(&rdata->cd.output.ldata, CD_TANGENT) == rdata->cd.layers.tangent_len);
|
|
|
|
|
2017-07-04 16:03:04 +03:00
|
|
|
int i_dst = 0;
|
|
|
|
for (int i_src = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
|
2017-06-28 13:38:24 +10:00
|
|
|
if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
|
|
|
|
i_dst--;
|
|
|
|
if (rdata->cd.layers.tangent_active >= i_src) {
|
|
|
|
rdata->cd.layers.tangent_active--;
|
2017-05-24 22:47:18 +10:00
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
2017-06-28 13:38:24 +10:00
|
|
|
else {
|
|
|
|
const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
|
2018-05-11 07:48:52 +02:00
|
|
|
uint hash = BLI_ghashutil_strhash_p(name);
|
2017-06-28 13:38:24 +10:00
|
|
|
|
|
|
|
BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
|
|
|
|
|
|
|
|
/* Done adding tangents. */
|
2017-05-24 22:47:18 +10:00
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
/* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT',
|
|
|
|
* not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */
|
|
|
|
|
|
|
|
/* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' */
|
|
|
|
rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
|
|
|
|
if (rdata->tri_len != 0) {
|
|
|
|
BLI_assert(rdata->cd.layers.tangent[i_dst] != NULL);
|
|
|
|
}
|
2017-06-02 16:42:39 +10:00
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
2017-07-04 16:03:04 +03:00
|
|
|
if (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) {
|
|
|
|
const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
|
2018-05-11 07:48:52 +02:00
|
|
|
uint hash = BLI_ghashutil_strhash_p(name);
|
2017-07-04 16:03:04 +03:00
|
|
|
BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
|
|
|
|
|
|
|
|
rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 08:50:45 +10:00
|
|
|
#undef me
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-24 22:47:18 +10:00
|
|
|
return rdata;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static void mesh_render_data_free(MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2018-05-30 12:40:16 +02:00
|
|
|
if (rdata->is_orco_allocated) {
|
|
|
|
MEM_SAFE_FREE(rdata->orco);
|
|
|
|
}
|
2017-05-22 17:21:22 +10:00
|
|
|
MEM_SAFE_FREE(rdata->cd.offset.uv);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.offset.vcol);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.uuid.auto_mix);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.uuid.uv);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.uuid.vcol);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.uuid.tangent);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.layers.uv);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.layers.vcol);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.layers.tangent);
|
|
|
|
MEM_SAFE_FREE(rdata->cd.layers.auto_vcol);
|
2017-05-01 17:58:15 +02:00
|
|
|
MEM_SAFE_FREE(rdata->loose_verts);
|
|
|
|
MEM_SAFE_FREE(rdata->loose_edges);
|
|
|
|
MEM_SAFE_FREE(rdata->edges_adjacent_polys);
|
|
|
|
MEM_SAFE_FREE(rdata->mlooptri);
|
2017-11-06 14:14:07 -02:00
|
|
|
MEM_SAFE_FREE(rdata->loop_normals);
|
2017-05-01 17:58:15 +02:00
|
|
|
MEM_SAFE_FREE(rdata->poly_normals);
|
2017-06-29 20:11:16 +10:00
|
|
|
MEM_SAFE_FREE(rdata->poly_normals_pack);
|
|
|
|
MEM_SAFE_FREE(rdata->vert_normals_pack);
|
2017-05-04 19:59:27 +02:00
|
|
|
MEM_SAFE_FREE(rdata->vert_weight_color);
|
2017-05-17 11:46:26 +10:00
|
|
|
MEM_SAFE_FREE(rdata->edge_select_bool);
|
2017-05-04 19:59:27 +02:00
|
|
|
MEM_SAFE_FREE(rdata->vert_color);
|
2017-05-09 08:50:45 +10:00
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
CustomData_free(&rdata->cd.output.ldata, rdata->loop_len);
|
2017-05-09 08:50:45 +10:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
MEM_freeN(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
|
|
|
|
{
|
|
|
|
return mesh_render_data_create_ex(me, types, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Accessor Functions
|
|
|
|
* \{ */
|
|
|
|
|
2017-05-09 10:38:52 +10:00
|
|
|
static const char *mesh_render_data_uv_auto_layer_uuid_get(const MeshRenderData *rdata, int layer)
|
2017-05-01 17:58:15 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_SHADING);
|
2017-05-22 17:21:22 +10:00
|
|
|
return rdata->cd.uuid.auto_mix[layer];
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 10:38:52 +10:00
|
|
|
static const char *mesh_render_data_vcol_auto_layer_uuid_get(const MeshRenderData *rdata, int layer)
|
2017-05-01 17:58:15 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_SHADING);
|
2017-05-22 17:21:22 +10:00
|
|
|
return rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + layer];
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 10:38:52 +10:00
|
|
|
static const char *mesh_render_data_uv_layer_uuid_get(const MeshRenderData *rdata, int layer)
|
2017-05-01 17:58:15 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_SHADING);
|
2017-05-22 17:21:22 +10:00
|
|
|
return rdata->cd.uuid.uv[layer];
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 10:38:52 +10:00
|
|
|
static const char *mesh_render_data_vcol_layer_uuid_get(const MeshRenderData *rdata, int layer)
|
2017-05-01 17:58:15 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_SHADING);
|
2017-05-22 17:21:22 +10:00
|
|
|
return rdata->cd.uuid.vcol[layer];
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-05-09 10:38:52 +10:00
|
|
|
static const char *mesh_render_data_tangent_layer_uuid_get(const MeshRenderData *rdata, int layer)
|
2017-05-01 17:58:15 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_SHADING);
|
2017-05-22 17:21:22 +10:00
|
|
|
return rdata->cd.uuid.tangent[layer];
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_verts_len_get(const MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
return rdata->vert_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_loose_verts_len_get(const MeshRenderData *rdata)
|
2017-02-28 14:30:34 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_OVERLAY);
|
|
|
|
return rdata->loose_vert_len;
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_edges_len_get(const MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_EDGE);
|
|
|
|
return rdata->edge_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_loose_edges_len_get(const MeshRenderData *rdata)
|
2017-02-28 14:30:34 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_OVERLAY);
|
|
|
|
return rdata->loose_edge_len;
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_looptri_len_get(const MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_LOOPTRI);
|
|
|
|
return rdata->tri_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-05-04 23:35:50 +10:00
|
|
|
static int mesh_render_data_mat_len_get(const MeshRenderData *rdata)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_POLY);
|
2017-05-04 23:35:50 +10:00
|
|
|
return rdata->mat_len;
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int UNUSED_FUNCTION(mesh_render_data_loops_len_get)(const MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_LOOP);
|
|
|
|
return rdata->loop_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
static int mesh_render_data_polys_len_get(const MeshRenderData *rdata)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_POLY);
|
|
|
|
return rdata->poly_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
2017-05-05 04:56:28 +10:00
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Internal Cache (Lazy Initialization)
|
|
|
|
* \{ */
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
/** Ensure #MeshRenderData.poly_normals_pack */
|
|
|
|
static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
|
2017-05-05 04:56:28 +10:00
|
|
|
{
|
2017-06-29 20:11:16 +10:00
|
|
|
Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack;
|
|
|
|
if (pnors_pack == NULL) {
|
2017-05-05 04:56:28 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter fiter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMFace *efa;
|
2017-05-05 04:56:28 +10:00
|
|
|
int i;
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH_INDEX(efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
2017-06-29 20:11:16 +10:00
|
|
|
pnors_pack[i] = GWN_normal_convert_i10_v3(efa->no);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float (*pnors)[3] = rdata->poly_normals;
|
|
|
|
|
|
|
|
if (!pnors) {
|
|
|
|
pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * rdata->poly_len, __func__);
|
|
|
|
BKE_mesh_calc_normals_poly(
|
|
|
|
rdata->mvert, NULL, rdata->vert_len,
|
|
|
|
rdata->mloop, rdata->mpoly, rdata->loop_len, rdata->poly_len, pnors, true);
|
|
|
|
}
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
|
2017-05-05 04:56:28 +10:00
|
|
|
for (int i = 0; i < rdata->poly_len; i++) {
|
2017-06-29 20:11:16 +10:00
|
|
|
pnors_pack[i] = GWN_normal_convert_i10_v3(pnors[i]);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
/** Ensure #MeshRenderData.vert_normals_pack */
|
|
|
|
static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata)
|
2017-05-05 04:56:28 +10:00
|
|
|
{
|
2017-06-29 20:11:16 +10:00
|
|
|
Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack;
|
|
|
|
if (vnors_pack == NULL) {
|
2017-05-05 04:56:28 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter viter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMVert *eve;
|
2017-05-05 04:56:28 +10:00
|
|
|
int i;
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
vnors_pack = rdata->vert_normals_pack = MEM_mallocN(sizeof(*vnors_pack) * rdata->vert_len, __func__);
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) {
|
2017-06-29 20:11:16 +10:00
|
|
|
vnors_pack[i] = GWN_normal_convert_i10_v3(eve->no);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* data from mesh used directly */
|
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Ensure #MeshRenderData.vert_color */
|
|
|
|
static void mesh_render_data_ensure_vert_color(MeshRenderData *rdata)
|
|
|
|
{
|
|
|
|
char (*vcol)[3] = rdata->vert_color;
|
|
|
|
if (vcol == NULL) {
|
|
|
|
if (rdata->edit_bmesh) {
|
2017-05-08 12:41:05 +10:00
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
|
|
|
|
if (cd_loop_color_offset == -1) {
|
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
|
|
|
|
|
|
|
|
BMIter fiter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMFace *efa;
|
2017-05-08 12:41:05 +10:00
|
|
|
int i = 0;
|
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
|
2017-05-08 12:41:05 +10:00
|
|
|
BMLoop *l_iter, *l_first;
|
2017-05-24 13:33:48 +10:00
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
|
2017-05-08 12:41:05 +10:00
|
|
|
do {
|
|
|
|
const MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_color_offset);
|
|
|
|
vcol[i][0] = lcol->r;
|
|
|
|
vcol[i][1] = lcol->g;
|
|
|
|
vcol[i][2] = lcol->b;
|
|
|
|
i += 1;
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
|
|
|
}
|
|
|
|
BLI_assert(i == rdata->loop_len);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-05-22 17:21:22 +10:00
|
|
|
if (rdata->mloopcol == NULL) {
|
2017-05-05 04:56:28 +10:00
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
|
|
|
|
|
|
|
|
for (int i = 0; i < rdata->loop_len; i++) {
|
2017-05-22 17:21:22 +10:00
|
|
|
vcol[i][0] = rdata->mloopcol[i].r;
|
|
|
|
vcol[i][1] = rdata->mloopcol[i].g;
|
|
|
|
vcol[i][2] = rdata->mloopcol[i].b;
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
fallback:
|
|
|
|
vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
|
|
|
|
|
|
|
|
for (int i = 0; i < rdata->loop_len; i++) {
|
|
|
|
vcol[i][0] = 255;
|
|
|
|
vcol[i][1] = 255;
|
|
|
|
vcol[i][2] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO, move into shader? */
|
|
|
|
static void rgb_from_weight(float r_rgb[3], const float weight)
|
|
|
|
{
|
|
|
|
const float blend = ((weight / 2.0f) + 0.5f);
|
|
|
|
|
|
|
|
if (weight <= 0.25f) { /* blue->cyan */
|
|
|
|
r_rgb[0] = 0.0f;
|
|
|
|
r_rgb[1] = blend * weight * 4.0f;
|
|
|
|
r_rgb[2] = blend;
|
|
|
|
}
|
|
|
|
else if (weight <= 0.50f) { /* cyan->green */
|
|
|
|
r_rgb[0] = 0.0f;
|
|
|
|
r_rgb[1] = blend;
|
|
|
|
r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f));
|
|
|
|
}
|
|
|
|
else if (weight <= 0.75f) { /* green->yellow */
|
|
|
|
r_rgb[0] = blend * ((weight - 0.50f) * 4.0f);
|
|
|
|
r_rgb[1] = blend;
|
|
|
|
r_rgb[2] = 0.0f;
|
|
|
|
}
|
|
|
|
else if (weight <= 1.0f) { /* yellow->red */
|
|
|
|
r_rgb[0] = blend;
|
|
|
|
r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f));
|
|
|
|
r_rgb[2] = 0.0f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* exceptional value, unclamped or nan,
|
|
|
|
* avoid uninitialized memory use */
|
|
|
|
r_rgb[0] = 1.0f;
|
|
|
|
r_rgb[1] = 0.0f;
|
|
|
|
r_rgb[2] = 1.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-17 17:14:10 +10:00
|
|
|
/** Ensure #MeshRenderData.vert_weight_color */
|
2017-05-05 04:56:28 +10:00
|
|
|
static void mesh_render_data_ensure_vert_weight_color(MeshRenderData *rdata, const int defgroup)
|
|
|
|
{
|
|
|
|
float (*vweight)[3] = rdata->vert_weight_color;
|
|
|
|
if (vweight == NULL) {
|
2017-06-01 13:35:27 +10:00
|
|
|
if (defgroup == -1) {
|
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
2017-05-05 04:56:28 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
|
|
|
|
if (cd_dvert_offset == -1) {
|
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
BMIter viter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMVert *eve;
|
2017-05-05 04:56:28 +10:00
|
|
|
int i;
|
|
|
|
|
|
|
|
vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__);
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) {
|
|
|
|
const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
2017-05-05 04:56:28 +10:00
|
|
|
float weight = defvert_find_weight(dvert, defgroup);
|
|
|
|
if (U.flag & USER_CUSTOM_RANGE) {
|
2017-12-07 23:53:03 +11:00
|
|
|
BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rgb_from_weight(vweight[i], weight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (rdata->dvert == NULL) {
|
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__);
|
|
|
|
for (int i = 0; i < rdata->vert_len; i++) {
|
|
|
|
float weight = defvert_find_weight(&rdata->dvert[i], defgroup);
|
|
|
|
if (U.flag & USER_CUSTOM_RANGE) {
|
2017-12-07 23:53:03 +11:00
|
|
|
BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
|
2017-05-05 04:56:28 +10:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rgb_from_weight(vweight[i], weight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
fallback:
|
|
|
|
vweight = rdata->vert_weight_color = MEM_callocN(sizeof(*vweight) * rdata->vert_len, __func__);
|
|
|
|
|
|
|
|
for (int i = 0; i < rdata->vert_len; i++) {
|
|
|
|
vweight[i][2] = 0.5f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-17 11:46:26 +10:00
|
|
|
/** Ensure #MeshRenderData.edge_select_bool */
|
|
|
|
static void mesh_render_data_ensure_edge_select_bool(MeshRenderData *rdata, bool use_wire)
|
2017-05-17 11:28:44 +10:00
|
|
|
{
|
2017-05-17 11:46:26 +10:00
|
|
|
bool *edge_select_bool = rdata->edge_select_bool;
|
|
|
|
if (edge_select_bool == NULL) {
|
|
|
|
edge_select_bool = rdata->edge_select_bool =
|
|
|
|
MEM_callocN(sizeof(*edge_select_bool) * rdata->edge_len, __func__);
|
2017-05-17 11:28:44 +10:00
|
|
|
|
|
|
|
for (int i = 0; i < rdata->poly_len; i++) {
|
|
|
|
MPoly *poly = &rdata->mpoly[i];
|
|
|
|
|
|
|
|
if (poly->flag & ME_FACE_SEL) {
|
|
|
|
for (int j = 0; j < poly->totloop; j++) {
|
|
|
|
MLoop *loop = &rdata->mloop[poly->loopstart + j];
|
|
|
|
if (use_wire) {
|
2017-05-17 11:46:26 +10:00
|
|
|
edge_select_bool[loop->e] = true;
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-05-17 11:46:26 +10:00
|
|
|
/* Not totally correct, will cause problems for edges with 3x faces. */
|
|
|
|
edge_select_bool[loop->e] = !edge_select_bool[loop->e];
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-05 04:56:28 +10:00
|
|
|
/** \} */
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Internal Cache Generation
|
|
|
|
* \{ */
|
|
|
|
|
2017-04-18 23:29:55 +10:00
|
|
|
static bool mesh_render_data_pnors_pcenter_select_get(
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata, const int poly,
|
2017-04-12 18:23:17 +10:00
|
|
|
float r_pnors[3], float r_center[3], bool *r_selected)
|
2017-03-02 01:07:03 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly);
|
|
|
|
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
2017-04-18 23:29:55 +10:00
|
|
|
return false;
|
|
|
|
}
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_face_calc_center_mean(efa, r_center);
|
2017-06-29 15:52:08 +10:00
|
|
|
copy_v3_v3(r_pnors, efa->no);
|
2017-05-24 13:33:48 +10:00
|
|
|
*r_selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false;
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-04-20 16:24:35 +10:00
|
|
|
MVert *mvert = rdata->mvert;
|
|
|
|
const MPoly *mpoly = rdata->mpoly + poly;
|
|
|
|
const MLoop *mloop = rdata->mloop + mpoly->loopstart;
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-04-12 18:23:17 +10:00
|
|
|
BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center);
|
|
|
|
BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, r_pnors);
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-04-12 18:23:17 +10:00
|
|
|
*r_selected = false; /* No selection if not in edit mode */
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
|
|
|
|
return true;
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
static bool mesh_render_data_edge_vcos_manifold_pnors(
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata, const int edge_index,
|
2017-04-18 23:29:55 +10:00
|
|
|
float **r_vco1, float **r_vco2, float **r_pnor1, float **r_pnor2, bool *r_is_manifold)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMEdge *eed = BM_edge_at_index(bm, edge_index);
|
|
|
|
if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
2017-04-18 23:29:55 +10:00
|
|
|
return false;
|
|
|
|
}
|
2017-05-24 13:33:48 +10:00
|
|
|
*r_vco1 = eed->v1->co;
|
|
|
|
*r_vco2 = eed->v2->co;
|
|
|
|
if (BM_edge_is_manifold(eed)) {
|
|
|
|
*r_pnor1 = eed->l->f->no;
|
|
|
|
*r_pnor2 = eed->l->radial_next->f->no;
|
2017-04-18 23:29:55 +10:00
|
|
|
*r_is_manifold = true;
|
|
|
|
}
|
2018-05-21 17:58:52 +02:00
|
|
|
else if (eed->l != NULL) {
|
2018-05-19 13:31:44 +02:00
|
|
|
*r_pnor1 = eed->l->f->no;
|
|
|
|
*r_pnor2 = eed->l->f->no;
|
2017-04-18 23:29:55 +10:00
|
|
|
*r_is_manifold = false;
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2018-05-21 17:58:52 +02:00
|
|
|
else {
|
|
|
|
*r_pnor1 = eed->v1->no;
|
|
|
|
*r_pnor2 = eed->v1->no;
|
|
|
|
*r_is_manifold = false;
|
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-04-20 16:24:35 +10:00
|
|
|
MVert *mvert = rdata->mvert;
|
|
|
|
MEdge *medge = rdata->medge;
|
|
|
|
EdgeAdjacentPolys *eap = rdata->edges_adjacent_polys;
|
|
|
|
float (*pnors)[3] = rdata->poly_normals;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
if (!eap) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const MLoop *mloop = rdata->mloop;
|
|
|
|
const MPoly *mpoly = rdata->mpoly;
|
|
|
|
const int poly_len = rdata->poly_len;
|
2018-05-21 17:58:52 +02:00
|
|
|
const bool do_pnors = (poly_len != 0 && pnors == NULL);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2018-05-21 17:58:52 +02:00
|
|
|
eap = rdata->edges_adjacent_polys = MEM_mallocN(sizeof(*eap) * rdata->edge_len, __func__);
|
|
|
|
for (int i = 0; i < rdata->edge_len; i++) {
|
|
|
|
eap[i].count = 0;
|
|
|
|
eap[i].face_index[0] = -1;
|
|
|
|
eap[i].face_index[1] = -1;
|
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
if (do_pnors) {
|
2017-04-20 16:24:35 +10:00
|
|
|
pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * poly_len, __func__);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
for (int i = 0; i < poly_len; i++, mpoly++) {
|
2017-02-23 11:54:40 +01:00
|
|
|
if (do_pnors) {
|
|
|
|
BKE_mesh_calc_poly_normal(mpoly, mloop + mpoly->loopstart, mvert, pnors[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int loopend = mpoly->loopstart + mpoly->totloop;
|
|
|
|
for (int j = mpoly->loopstart; j < loopend; j++) {
|
|
|
|
const int edge_idx = mloop[j].e;
|
|
|
|
if (eap[edge_idx].count < 2) {
|
|
|
|
eap[edge_idx].face_index[eap[edge_idx].count] = i;
|
|
|
|
}
|
|
|
|
eap[edge_idx].count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-21 17:58:52 +02:00
|
|
|
BLI_assert(eap && (rdata->poly_len == 0 || pnors != NULL));
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
*r_vco1 = mvert[medge[edge_index].v1].co;
|
|
|
|
*r_vco2 = mvert[medge[edge_index].v2].co;
|
2018-05-21 17:58:52 +02:00
|
|
|
if (eap[edge_index].face_index[0] == -1) {
|
|
|
|
/* Edge has no poly... */
|
|
|
|
*r_pnor1 = *r_pnor2 = mvert[medge[edge_index].v1].co; /* XXX mvert.no are shorts... :( */
|
|
|
|
*r_is_manifold = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*r_pnor1 = pnors[eap[edge_index].face_index[0]];
|
2018-05-19 13:31:44 +02:00
|
|
|
|
2018-05-21 17:58:52 +02:00
|
|
|
float nor[3], v1[3], v2[3], r_center[3];
|
|
|
|
const MPoly *mpoly = rdata->mpoly + eap[edge_index].face_index[0];
|
|
|
|
const MLoop *mloop = rdata->mloop + mpoly->loopstart;
|
2018-05-19 13:31:44 +02:00
|
|
|
|
2018-05-21 17:58:52 +02:00
|
|
|
BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center);
|
|
|
|
sub_v3_v3v3(v1, *r_vco2, *r_vco1);
|
|
|
|
sub_v3_v3v3(v2, r_center, *r_vco1);
|
|
|
|
cross_v3_v3v3(nor, v1, v2);
|
2018-05-19 13:31:44 +02:00
|
|
|
|
2018-05-21 17:58:52 +02:00
|
|
|
if (dot_v3v3(nor, *r_pnor1) < 0.0) {
|
|
|
|
SWAP(float *, *r_vco1, *r_vco2);
|
|
|
|
}
|
2018-05-19 13:31:44 +02:00
|
|
|
|
2018-05-21 17:58:52 +02:00
|
|
|
if (eap[edge_index].count == 2) {
|
|
|
|
BLI_assert(eap[edge_index].face_index[1] >= 0);
|
|
|
|
*r_pnor2 = pnors[eap[edge_index].face_index[1]];
|
|
|
|
*r_is_manifold = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*r_pnor2 = pnors[eap[edge_index].face_index[0]];
|
|
|
|
*r_is_manifold = false;
|
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-18 23:29:55 +10:00
|
|
|
return true;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
/* First 2 bytes are bit flags
|
|
|
|
* 3rd is for sharp edges
|
|
|
|
* 4rd is for creased edges */
|
|
|
|
enum {
|
|
|
|
VFLAG_VERTEX_ACTIVE = 1 << 0,
|
|
|
|
VFLAG_VERTEX_SELECTED = 1 << 1,
|
|
|
|
VFLAG_FACE_ACTIVE = 1 << 2,
|
|
|
|
VFLAG_FACE_SELECTED = 1 << 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
VFLAG_EDGE_EXISTS = 1 << 0,
|
|
|
|
VFLAG_EDGE_ACTIVE = 1 << 1,
|
|
|
|
VFLAG_EDGE_SELECTED = 1 << 2,
|
|
|
|
VFLAG_EDGE_SEAM = 1 << 3,
|
|
|
|
VFLAG_EDGE_SHARP = 1 << 4,
|
|
|
|
/* Beware to not go over 1 << 7
|
2017-04-13 14:13:46 +10:00
|
|
|
* (see gpu_shader_edit_mesh_overlay_geom.glsl) */
|
2017-03-01 14:07:04 +01:00
|
|
|
};
|
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
static unsigned char mesh_render_data_looptri_flag(MeshRenderData *rdata, const BMFace *efa)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
|
|
|
unsigned char fflag = 0;
|
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (efa == rdata->efa_act)
|
2017-05-24 11:43:55 +10:00
|
|
|
fflag |= VFLAG_FACE_ACTIVE;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
|
2017-05-24 11:43:55 +10:00
|
|
|
fflag |= VFLAG_FACE_SELECTED;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
|
|
|
return fflag;
|
|
|
|
}
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
static void mesh_render_data_edge_flag(
|
2017-05-24 13:33:48 +10:00
|
|
|
const MeshRenderData *rdata, const BMEdge *eed,
|
2017-05-24 11:43:55 +10:00
|
|
|
EdgeDrawAttr *eattr)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
2017-05-24 11:43:55 +10:00
|
|
|
eattr->e_flag |= VFLAG_EDGE_EXISTS;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (eed == rdata->eed_act)
|
2017-05-24 11:43:55 +10:00
|
|
|
eattr->e_flag |= VFLAG_EDGE_ACTIVE;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
|
2017-05-24 11:43:55 +10:00
|
|
|
eattr->e_flag |= VFLAG_EDGE_SELECTED;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (BM_elem_flag_test(eed, BM_ELEM_SEAM))
|
2017-05-24 11:43:55 +10:00
|
|
|
eattr->e_flag |= VFLAG_EDGE_SEAM;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
|
2017-05-24 11:43:55 +10:00
|
|
|
eattr->e_flag |= VFLAG_EDGE_SHARP;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
/* Use a byte for value range */
|
|
|
|
if (rdata->cd.offset.crease != -1) {
|
2017-05-24 13:33:48 +10:00
|
|
|
float crease = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.crease);
|
2017-05-24 11:43:55 +10:00
|
|
|
if (crease > 0) {
|
|
|
|
eattr->crease = (char)(crease * 255.0f);
|
2017-04-12 13:42:27 +10:00
|
|
|
}
|
2017-05-24 11:43:55 +10:00
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
/* Use a byte for value range */
|
|
|
|
if (rdata->cd.offset.bweight != -1) {
|
2017-05-24 13:33:48 +10:00
|
|
|
float bweight = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.bweight);
|
2017-05-24 11:43:55 +10:00
|
|
|
if (bweight > 0) {
|
|
|
|
eattr->bweight = (char)(bweight * 255.0f);
|
2017-03-01 14:07:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
static unsigned char mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *eve)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
unsigned char vflag = 0;
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
/* Current vertex */
|
2017-05-24 13:33:48 +10:00
|
|
|
if (eve == rdata->eve_act)
|
2017-05-24 11:43:55 +10:00
|
|
|
vflag |= VFLAG_VERTEX_ACTIVE;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
|
2017-05-24 11:43:55 +10:00
|
|
|
vflag |= VFLAG_VERTEX_SELECTED;
|
2017-03-01 14:07:04 +01:00
|
|
|
|
|
|
|
return vflag;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_overlay_tri(
|
2017-06-19 20:18:04 +10:00
|
|
|
MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
|
2018-05-11 07:48:52 +02:00
|
|
|
const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id,
|
2017-05-24 11:43:55 +10:00
|
|
|
const BMLoop **bm_looptri, const int base_vert_idx)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
2017-05-13 16:45:06 +02:00
|
|
|
unsigned char fflag;
|
|
|
|
unsigned char vflag;
|
|
|
|
|
|
|
|
if (vbo_pos) {
|
2018-04-19 11:03:58 +02:00
|
|
|
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
|
|
|
|
if (rdata->edit_data && rdata->edit_data->vertexCos) {
|
|
|
|
for (uint i = 0; i < 3; i++) {
|
|
|
|
int vidx = BM_elem_index_get(bm_looptri[i]->v);
|
|
|
|
const float *pos = rdata->edit_data->vertexCos[vidx];
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (uint i = 0; i < 3; i++) {
|
|
|
|
const float *pos = bm_looptri[i]->v->co;
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
|
|
|
|
}
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vbo_nor) {
|
2017-05-24 11:43:55 +10:00
|
|
|
/* TODO real loop normal */
|
2017-06-29 18:52:39 +10:00
|
|
|
Gwn_PackedNormal lnor = GWN_normal_convert_i10_v3(bm_looptri[0]->f->no);
|
2017-05-24 11:43:55 +10:00
|
|
|
for (uint i = 0; i < 3; i++) {
|
2017-06-29 18:52:39 +10:00
|
|
|
Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(bm_looptri[i]->v->no);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
|
|
|
|
GWN_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vbo_data) {
|
2017-05-24 11:43:55 +10:00
|
|
|
fflag = mesh_render_data_looptri_flag(rdata, bm_looptri[0]->f);
|
|
|
|
uint i_prev = 1, i = 2;
|
|
|
|
for (uint i_next = 0; i_next < 3; i_next++) {
|
|
|
|
vflag = mesh_render_data_vertex_flag(rdata, bm_looptri[i]->v);
|
|
|
|
EdgeDrawAttr eattr = {0};
|
|
|
|
if (bm_looptri[i_next] == bm_looptri[i_prev]->prev) {
|
|
|
|
mesh_render_data_edge_flag(rdata, bm_looptri[i_next]->e, &eattr);
|
|
|
|
}
|
|
|
|
eattr.v_flag = fflag | vflag;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
|
2017-05-24 11:43:55 +10:00
|
|
|
|
|
|
|
i_prev = i;
|
|
|
|
i = i_next;
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void add_overlay_loose_edge(
|
2017-06-19 20:18:04 +10:00
|
|
|
MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
|
2018-05-11 07:48:52 +02:00
|
|
|
const uint pos_id, const uint vnor_id, const uint data_id,
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMEdge *eed, const int base_vert_idx)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
2017-05-13 16:45:06 +02:00
|
|
|
if (vbo_pos) {
|
2018-04-19 11:03:58 +02:00
|
|
|
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
|
|
|
|
if (rdata->edit_data && rdata->edit_data->vertexCos) {
|
|
|
|
for (uint i = 0; i < 2; i++) {
|
|
|
|
int vidx = BM_elem_index_get((&eed->v1)[i]);
|
|
|
|
const float *pos = rdata->edit_data->vertexCos[vidx];
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
|
|
const float *pos = (&eed->v1)[i]->co;
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
|
|
|
|
}
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-13 16:45:06 +02:00
|
|
|
if (vbo_nor) {
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
2017-06-29 18:52:39 +10:00
|
|
|
Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3((&eed->v1)[i]->no);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vbo_data) {
|
2017-05-24 11:43:55 +10:00
|
|
|
EdgeDrawAttr eattr = {0};
|
2017-05-24 13:33:48 +10:00
|
|
|
mesh_render_data_edge_flag(rdata, eed, &eattr);
|
2017-05-13 16:45:06 +02:00
|
|
|
for (int i = 0; i < 2; ++i) {
|
2017-05-24 13:33:48 +10:00
|
|
|
eattr.v_flag = mesh_render_data_vertex_flag(rdata, (&eed->v1)[i]);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void add_overlay_loose_vert(
|
2017-06-19 20:18:04 +10:00
|
|
|
MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
|
2018-05-11 07:48:52 +02:00
|
|
|
const uint pos_id, const uint vnor_id, const uint data_id,
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMVert *eve, const int base_vert_idx)
|
2017-03-01 14:07:04 +01:00
|
|
|
{
|
2017-05-13 16:45:06 +02:00
|
|
|
if (vbo_pos) {
|
2018-04-19 11:03:58 +02:00
|
|
|
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
|
|
|
|
if (rdata->edit_data && rdata->edit_data->vertexCos) {
|
|
|
|
int vidx = BM_elem_index_get(eve);
|
|
|
|
const float *pos = rdata->edit_data->vertexCos[vidx];
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const float *pos = eve->co;
|
|
|
|
GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
|
|
|
|
}
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vbo_nor) {
|
2017-06-29 18:52:39 +10:00
|
|
|
Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(eve->no);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vbo_data) {
|
|
|
|
unsigned char vflag[4] = {0, 0, 0, 0};
|
2017-05-24 13:33:48 +10:00
|
|
|
vflag[0] = mesh_render_data_vertex_flag(rdata, eve);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
}
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
/* ---------------------------------------------------------------------- */
|
2017-05-05 05:07:52 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/** \name Mesh Gwn_Batch Cache
|
2017-05-05 05:07:52 +10:00
|
|
|
* \{ */
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
typedef struct MeshBatchCache {
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *pos_in_order;
|
|
|
|
Gwn_VertBuf *nor_in_order;
|
|
|
|
Gwn_IndexBuf *edges_in_order;
|
2018-05-19 13:31:44 +02:00
|
|
|
Gwn_IndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBuf *triangles_in_order;
|
|
|
|
|
|
|
|
Gwn_Batch *all_verts;
|
|
|
|
Gwn_Batch *all_edges;
|
|
|
|
Gwn_Batch *all_triangles;
|
|
|
|
|
|
|
|
Gwn_VertBuf *pos_with_normals;
|
|
|
|
Gwn_VertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
|
2017-08-17 01:38:07 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Other uses are all positions or loose elements.
|
|
|
|
* This stores all visible elements, needed for selection.
|
|
|
|
*/
|
|
|
|
Gwn_VertBuf *ed_fcenter_pos_with_nor_and_sel;
|
|
|
|
Gwn_VertBuf *ed_edge_pos;
|
|
|
|
Gwn_VertBuf *ed_vert_pos;
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *triangles_with_normals;
|
2017-05-17 16:01:18 +10:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
/* Skip hidden (depending on paint select mode) */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *triangles_with_weights;
|
|
|
|
Gwn_Batch *triangles_with_vert_colors;
|
2017-05-17 16:01:18 +10:00
|
|
|
/* Always skip hidden */
|
2017-08-17 01:38:07 +10:00
|
|
|
Gwn_Batch *triangles_with_select_mask;
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *triangles_with_select_id;
|
2017-08-17 01:38:07 +10:00
|
|
|
uint triangles_with_select_id_offset;
|
|
|
|
|
|
|
|
Gwn_Batch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */
|
|
|
|
Gwn_Batch *edges_with_select_id;
|
|
|
|
Gwn_Batch *verts_with_select_id;
|
|
|
|
|
|
|
|
uint facedot_with_select_id_offset;
|
|
|
|
uint edges_with_select_id_offset;
|
|
|
|
uint verts_with_select_id_offset;
|
2017-05-17 16:01:18 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *points_with_normals;
|
|
|
|
Gwn_Batch *fancy_edges; /* owns its vertex buffer (not shared) */
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2018-05-19 13:31:44 +02:00
|
|
|
Gwn_Batch *edge_detection;
|
|
|
|
|
2017-04-25 18:46:59 +02:00
|
|
|
/* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
|
|
|
|
* to minimise data transfer for skinned mesh. */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertFormat shaded_triangles_format;
|
|
|
|
Gwn_VertBuf *shaded_triangles_data;
|
|
|
|
Gwn_IndexBuf **shaded_triangles_in_order;
|
|
|
|
Gwn_Batch **shaded_triangles;
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-05-22 23:31:46 +10:00
|
|
|
/* Texture Paint.*/
|
|
|
|
/* per-texture batch */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch **texpaint_triangles;
|
|
|
|
Gwn_Batch *texpaint_triangles_single;
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2017-05-13 16:45:06 +02:00
|
|
|
/* Edit Cage Mesh buffers */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *ed_tri_pos;
|
|
|
|
Gwn_VertBuf *ed_tri_nor; /* LoopNor, VertNor */
|
|
|
|
Gwn_VertBuf *ed_tri_data;
|
2017-05-13 16:45:06 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *ed_ledge_pos;
|
|
|
|
Gwn_VertBuf *ed_ledge_nor; /* VertNor */
|
|
|
|
Gwn_VertBuf *ed_ledge_data;
|
2017-05-13 16:45:06 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *ed_lvert_pos;
|
|
|
|
Gwn_VertBuf *ed_lvert_nor; /* VertNor */
|
|
|
|
Gwn_VertBuf *ed_lvert_data;
|
2017-05-13 16:45:06 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *overlay_triangles;
|
|
|
|
Gwn_Batch *overlay_triangles_nor; /* GWN_PRIM_POINTS */
|
|
|
|
Gwn_Batch *overlay_loose_edges;
|
|
|
|
Gwn_Batch *overlay_loose_edges_nor; /* GWN_PRIM_POINTS */
|
|
|
|
Gwn_Batch *overlay_loose_verts;
|
|
|
|
Gwn_Batch *overlay_facedots;
|
2017-05-13 16:45:06 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *overlay_weight_faces;
|
|
|
|
Gwn_Batch *overlay_weight_verts;
|
|
|
|
Gwn_Batch *overlay_paint_edges;
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2018-05-02 15:36:09 +02:00
|
|
|
/* arrays of bool uniform names (and value) that will be use to
|
|
|
|
* set srgb conversion for auto attribs.*/
|
|
|
|
char *auto_layer_names;
|
|
|
|
int *auto_layer_is_srgb;
|
|
|
|
int auto_layer_ct;
|
|
|
|
|
2017-01-26 18:56:52 +01:00
|
|
|
/* settings to determine if cache is invalid */
|
2017-08-22 22:04:40 +10:00
|
|
|
bool is_maybe_dirty;
|
|
|
|
bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
|
2017-04-19 00:10:32 +10:00
|
|
|
int edge_len;
|
|
|
|
int tri_len;
|
|
|
|
int poly_len;
|
|
|
|
int vert_len;
|
2017-05-04 23:35:50 +10:00
|
|
|
int mat_len;
|
2017-01-25 09:16:29 +01:00
|
|
|
bool is_editmode;
|
2017-07-13 00:27:06 +10:00
|
|
|
|
|
|
|
/* XXX, only keep for as long as sculpt mode uses shaded drawing. */
|
|
|
|
bool is_sculpt_points_tag;
|
2018-05-21 13:21:26 +02:00
|
|
|
|
|
|
|
/* Valid only if edges_adjacency is up to date. */
|
|
|
|
bool is_manifold;
|
2017-01-25 09:16:29 +01:00
|
|
|
} MeshBatchCache;
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/* Gwn_Batch cache management. */
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
static bool mesh_batch_cache_valid(Mesh *me)
|
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
if (cache == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-25 18:46:59 +02:00
|
|
|
/* XXX find another place for this */
|
2017-05-04 23:35:50 +10:00
|
|
|
if (cache->mat_len != mesh_render_mat_len_get(me)) {
|
2017-08-22 22:04:40 +10:00
|
|
|
cache->is_maybe_dirty = true;
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
if (cache->is_editmode != (me->edit_btmesh != NULL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-22 22:04:40 +10:00
|
|
|
if (cache->is_dirty) {
|
2017-05-03 18:55:40 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-22 22:04:40 +10:00
|
|
|
if (cache->is_maybe_dirty == false) {
|
2017-01-26 18:56:52 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
2017-01-26 19:08:27 +01:00
|
|
|
if (cache->is_editmode) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-04-19 00:10:32 +10:00
|
|
|
else if ((cache->vert_len != mesh_render_verts_len_get(me)) ||
|
|
|
|
(cache->edge_len != mesh_render_edges_len_get(me)) ||
|
|
|
|
(cache->tri_len != mesh_render_looptri_len_get(me)) ||
|
2017-04-25 18:46:59 +02:00
|
|
|
(cache->poly_len != mesh_render_polys_len_get(me)) ||
|
2017-05-04 23:35:50 +10:00
|
|
|
(cache->mat_len != mesh_render_mat_len_get(me)))
|
2017-01-26 18:56:52 +01:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_batch_cache_init(Mesh *me)
|
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2017-02-23 11:54:40 +01:00
|
|
|
|
|
|
|
if (!cache) {
|
2018-05-02 15:47:45 +02:00
|
|
|
cache = me->runtime.batch_cache = MEM_callocN(sizeof(*cache), __func__);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
memset(cache, 0, sizeof(*cache));
|
|
|
|
}
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
cache->is_editmode = me->edit_btmesh != NULL;
|
|
|
|
|
2017-01-26 19:08:27 +01:00
|
|
|
if (cache->is_editmode == false) {
|
2017-04-19 00:10:32 +10:00
|
|
|
cache->edge_len = mesh_render_edges_len_get(me);
|
|
|
|
cache->tri_len = mesh_render_looptri_len_get(me);
|
|
|
|
cache->poly_len = mesh_render_polys_len_get(me);
|
|
|
|
cache->vert_len = mesh_render_verts_len_get(me);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
2017-01-26 18:56:52 +01:00
|
|
|
|
2017-05-04 23:35:50 +10:00
|
|
|
cache->mat_len = mesh_render_mat_len_get(me);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-08-22 22:04:40 +10:00
|
|
|
cache->is_maybe_dirty = false;
|
2017-01-26 18:56:52 +01:00
|
|
|
cache->is_dirty = false;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
|
|
|
|
{
|
|
|
|
if (!mesh_batch_cache_valid(me)) {
|
2017-04-21 21:14:11 +10:00
|
|
|
mesh_batch_cache_clear(me);
|
2017-01-25 09:16:29 +01:00
|
|
|
mesh_batch_cache_init(me);
|
|
|
|
}
|
2018-05-02 15:47:45 +02:00
|
|
|
return me->runtime.batch_cache;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2017-04-21 21:14:11 +10:00
|
|
|
if (cache == NULL) {
|
|
|
|
return;
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
2017-04-21 21:14:11 +10:00
|
|
|
switch (mode) {
|
2017-08-22 22:04:40 +10:00
|
|
|
case BKE_MESH_BATCH_DIRTY_MAYBE_ALL:
|
|
|
|
cache->is_maybe_dirty = true;
|
2017-04-21 21:14:11 +10:00
|
|
|
break;
|
|
|
|
case BKE_MESH_BATCH_DIRTY_SELECT:
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
|
2017-08-17 01:38:07 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
|
2017-08-17 01:38:07 +10:00
|
|
|
/* Edit mode selection. */
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
|
2017-04-21 21:14:11 +10:00
|
|
|
break;
|
2017-08-22 22:04:40 +10:00
|
|
|
case BKE_MESH_BATCH_DIRTY_ALL:
|
|
|
|
cache->is_dirty = true;
|
2017-05-03 18:55:40 +02:00
|
|
|
break;
|
2017-07-10 14:43:57 +02:00
|
|
|
case BKE_MESH_BATCH_DIRTY_SHADING:
|
2017-07-11 12:52:04 +02:00
|
|
|
/* TODO: This should only update UV and tangent data,
|
|
|
|
* and not free the entire cache. */
|
2017-08-22 22:04:40 +10:00
|
|
|
cache->is_dirty = true;
|
2017-07-10 14:43:57 +02:00
|
|
|
break;
|
2017-07-13 00:27:06 +10:00
|
|
|
case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS:
|
|
|
|
cache->is_sculpt_points_tag = true;
|
|
|
|
break;
|
2017-04-21 21:14:11 +10:00
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2017-03-06 03:58:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-15 13:55:20 +01:00
|
|
|
/**
|
|
|
|
* This only clear the batches associated to the given vertex buffer.
|
|
|
|
**/
|
|
|
|
static void mesh_batch_cache_clear_selective(Mesh *me, Gwn_VertBuf *vert)
|
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2018-03-15 13:55:20 +01:00
|
|
|
if (!cache) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_assert(vert != NULL);
|
|
|
|
|
|
|
|
if (cache->pos_with_normals == vert) {
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
|
|
|
|
if (cache->shaded_triangles) {
|
|
|
|
for (int i = 0; i < cache->mat_len; ++i) {
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MEM_SAFE_FREE(cache->shaded_triangles);
|
|
|
|
if (cache->texpaint_triangles) {
|
|
|
|
for (int i = 0; i < cache->mat_len; ++i) {
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MEM_SAFE_FREE(cache->texpaint_triangles);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
|
|
|
|
}
|
|
|
|
/* TODO: add the other ones if needed. */
|
|
|
|
else {
|
|
|
|
/* Does not match any vertbuf in the batch cache! */
|
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
static void mesh_batch_cache_clear(Mesh *me)
|
2017-02-23 11:54:40 +01:00
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
MeshBatchCache *cache = me->runtime.batch_cache;
|
2017-02-23 11:54:40 +01:00
|
|
|
if (!cache) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->all_verts);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->all_edges);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->all_triangles);
|
|
|
|
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
|
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
|
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
|
|
|
|
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
|
|
|
|
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
|
2017-08-17 01:38:07 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
|
2017-08-17 01:38:07 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->fancy_edges);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2018-05-19 13:31:44 +02:00
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency);
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->edge_detection);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
|
2017-04-25 18:46:59 +02:00
|
|
|
if (cache->shaded_triangles_in_order) {
|
2017-05-04 23:35:50 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cache->shaded_triangles) {
|
2017-05-04 23:35:50 +10:00
|
|
|
for (int i = 0; i < cache->mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(cache->shaded_triangles_in_order);
|
|
|
|
MEM_SAFE_FREE(cache->shaded_triangles);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2018-05-02 15:36:09 +02:00
|
|
|
MEM_SAFE_FREE(cache->auto_layer_names);
|
|
|
|
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
|
|
|
|
|
2017-05-22 23:31:46 +10:00
|
|
|
if (cache->texpaint_triangles) {
|
|
|
|
for (int i = 0; i < cache->mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
MEM_SAFE_FREE(cache->texpaint_triangles);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
|
2017-04-21 21:14:11 +10:00
|
|
|
void DRW_mesh_batch_cache_free(Mesh *me)
|
2017-02-23 11:54:40 +01:00
|
|
|
{
|
2017-04-21 21:14:11 +10:00
|
|
|
mesh_batch_cache_clear(me);
|
2018-05-02 15:47:45 +02:00
|
|
|
MEM_SAFE_FREE(me->runtime.batch_cache);
|
2017-02-23 11:54:40 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/* Gwn_Batch cache usage. */
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
2017-05-22 16:20:54 +10:00
|
|
|
#define USE_COMP_MESH_DATA
|
2017-04-25 18:46:59 +02:00
|
|
|
|
|
|
|
if (cache->shaded_triangles_data == NULL) {
|
2017-06-30 18:01:20 +10:00
|
|
|
const uint uv_len = rdata->cd.layers.uv_len;
|
|
|
|
const uint tangent_len = rdata->cd.layers.tangent_len;
|
|
|
|
const uint vcol_len = rdata->cd.layers.vcol_len;
|
|
|
|
const uint layers_combined_len = uv_len + vcol_len + tangent_len;
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
if (layers_combined_len == 0) {
|
2017-05-15 16:12:51 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertFormat *format = &cache->shaded_triangles_format;
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_clear(format);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
|
|
|
/* initialize vertex format */
|
2017-06-30 18:01:20 +10:00
|
|
|
uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len);
|
|
|
|
uint *uv_id = layers_combined_id;
|
|
|
|
uint *tangent_id = uv_id + uv_len;
|
|
|
|
uint *vcol_id = tangent_id + tangent_len;
|
|
|
|
|
|
|
|
/* Not needed, just for sanity. */
|
|
|
|
if (uv_len == 0) { uv_id = NULL; }
|
|
|
|
if (tangent_len == 0) { tangent_id = NULL; }
|
|
|
|
if (vcol_len == 0) { vcol_id = NULL; }
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2018-05-02 15:36:09 +02:00
|
|
|
/* Count number of auto layer and allocate big enough name buffer. */
|
|
|
|
uint auto_names_len = 0;
|
|
|
|
uint auto_ofs = 0;
|
|
|
|
uint auto_id = 0;
|
|
|
|
cache->auto_layer_ct = 0;
|
|
|
|
for (uint i = 0; i < uv_len; i++) {
|
|
|
|
const char *attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
|
|
|
|
auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */
|
|
|
|
cache->auto_layer_ct++;
|
|
|
|
}
|
|
|
|
for (uint i = 0; i < vcol_len; i++) {
|
|
|
|
if (rdata->cd.layers.auto_vcol[i]) {
|
|
|
|
const char *attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
|
|
|
|
auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */
|
|
|
|
cache->auto_layer_ct++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto_names_len += 1; /* add an ultimate '\0' terminator */
|
|
|
|
cache->auto_layer_names = MEM_callocN(auto_names_len * sizeof(char), "Auto layer name buf");
|
|
|
|
cache->auto_layer_is_srgb = MEM_mallocN(cache->auto_layer_ct * sizeof(int), "Auto layer value buf");
|
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint i = 0; i < uv_len; i++) {
|
2017-05-01 17:58:15 +02:00
|
|
|
/* UV */
|
2017-06-30 18:01:20 +10:00
|
|
|
const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i);
|
2017-05-15 17:55:02 +02:00
|
|
|
#if defined(USE_COMP_MESH_DATA) && 0 /* these are clamped. Maybe use them as an option in the future */
|
2017-06-19 20:18:04 +10:00
|
|
|
uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-05-14 16:13:00 +02:00
|
|
|
#else
|
2017-06-19 20:18:04 +10:00
|
|
|
uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
2017-05-14 16:13:00 +02:00
|
|
|
#endif
|
2017-05-01 17:58:15 +02:00
|
|
|
|
|
|
|
/* Auto Name */
|
2017-05-09 10:38:52 +10:00
|
|
|
attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_alias_add(format, attrib_name);
|
2017-05-13 22:53:11 +02:00
|
|
|
|
2018-05-02 15:36:09 +02:00
|
|
|
/* +1 include null terminator. */
|
2018-05-26 10:41:25 +02:00
|
|
|
auto_ofs += 1 + BLI_snprintf_rlen(
|
|
|
|
cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name);
|
2018-05-02 15:36:09 +02:00
|
|
|
cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */
|
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
if (i == rdata->cd.layers.uv_active) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_alias_add(format, "u");
|
2017-05-13 22:53:11 +02:00
|
|
|
}
|
2017-06-28 09:55:40 +10:00
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint i = 0; i < tangent_len; i++) {
|
|
|
|
const char *attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i);
|
2017-05-18 14:29:57 +02:00
|
|
|
/* WATCH IT : only specifying 3 component instead of 4 (4th is sign).
|
|
|
|
* That may cause some problem but I could not make it to fail (fclem) */
|
2017-05-14 16:13:00 +02:00
|
|
|
#ifdef USE_COMP_MESH_DATA
|
2017-05-21 15:59:34 -04:00
|
|
|
/* Tangents need more precision than 10_10_10 */
|
2017-06-19 20:18:04 +10:00
|
|
|
tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-05-14 16:13:00 +02:00
|
|
|
#else
|
2017-06-19 20:18:04 +10:00
|
|
|
tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-05-14 16:13:00 +02:00
|
|
|
#endif
|
2017-05-13 22:53:11 +02:00
|
|
|
|
2017-06-28 09:55:40 +10:00
|
|
|
if (i == rdata->cd.layers.tangent_active) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_alias_add(format, "t");
|
2017-05-13 22:53:11 +02:00
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint i = 0; i < vcol_len; i++) {
|
|
|
|
const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i);
|
2017-06-19 20:18:04 +10:00
|
|
|
vcol_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-05-01 17:58:15 +02:00
|
|
|
|
|
|
|
/* Auto layer */
|
2017-05-22 17:21:22 +10:00
|
|
|
if (rdata->cd.layers.auto_vcol[i]) {
|
2017-05-09 10:38:52 +10:00
|
|
|
attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
|
2018-05-02 15:36:09 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_alias_add(format, attrib_name);
|
2018-05-02 15:36:09 +02:00
|
|
|
|
|
|
|
/* +1 include null terminator. */
|
2018-05-26 10:41:25 +02:00
|
|
|
auto_ofs += 1 + BLI_snprintf_rlen(
|
|
|
|
cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name);
|
2018-05-02 15:36:09 +02:00
|
|
|
cache->auto_layer_is_srgb[auto_id++] = 1; /* tag as srgb */
|
2017-05-13 22:53:11 +02:00
|
|
|
}
|
|
|
|
|
2017-05-22 17:21:22 +10:00
|
|
|
if (i == rdata->cd.layers.vcol_active) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertformat_alias_add(format, "c");
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
const uint tri_len = mesh_render_data_looptri_len_get(rdata);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = cache->shaded_triangles_data = GWN_vertbuf_create_with_format(format);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
Gwn_VertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
|
|
|
|
|
|
|
|
Gwn_VertBufRaw *uv_step = layers_combined_step;
|
|
|
|
Gwn_VertBufRaw *tangent_step = uv_step + uv_len;
|
|
|
|
Gwn_VertBufRaw *vcol_step = tangent_step + tangent_len;
|
|
|
|
|
|
|
|
/* Not needed, just for sanity. */
|
|
|
|
if (uv_len == 0) { uv_step = NULL; }
|
|
|
|
if (tangent_len == 0) { tangent_step = NULL; }
|
|
|
|
if (vcol_len == 0) { vcol_step = NULL; }
|
|
|
|
|
|
|
|
for (uint i = 0; i < uv_len; i++) {
|
|
|
|
GWN_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
|
|
|
|
}
|
|
|
|
for (uint i = 0; i < tangent_len; i++) {
|
|
|
|
GWN_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
|
|
|
|
}
|
|
|
|
for (uint i = 0; i < vcol_len; i++) {
|
|
|
|
GWN_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
/* TODO deduplicate all verts and make use of Gwn_IndexBuf in
|
2017-05-23 17:48:05 +10:00
|
|
|
* mesh_batch_cache_get_triangles_in_order_split_by_material. */
|
2017-06-30 18:01:20 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
for (uint i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
|
|
|
if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-06-28 09:55:40 +10:00
|
|
|
/* UVs */
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint j = 0; j < uv_len; j++) {
|
|
|
|
const uint layer_offset = rdata->cd.offset.uv[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->uv;
|
|
|
|
copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
|
|
|
|
}
|
2017-06-28 09:55:40 +10:00
|
|
|
}
|
2017-06-30 18:01:20 +10:00
|
|
|
/* TANGENTs */
|
|
|
|
for (uint j = 0; j < tangent_len; j++) {
|
|
|
|
float (*layer_data)[4] = rdata->cd.layers.tangent[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *elem = layer_data[BM_elem_index_get(bm_looptri[t])];
|
|
|
|
normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* VCOLs */
|
|
|
|
for (uint j = 0; j < vcol_len; j++) {
|
|
|
|
const uint layer_offset = rdata->cd.offset.vcol[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->r;
|
|
|
|
copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (uint i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
2017-06-28 09:55:40 +10:00
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
/* UVs */
|
|
|
|
for (uint j = 0; j < uv_len; j++) {
|
|
|
|
const MLoopUV *layer_data = rdata->cd.layers.uv[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *elem = layer_data[mlt->tri[t]].uv;
|
|
|
|
copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
|
|
|
|
}
|
|
|
|
}
|
2017-06-28 09:55:40 +10:00
|
|
|
/* TANGENTs */
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint j = 0; j < tangent_len; j++) {
|
|
|
|
float (*layer_data)[4] = rdata->cd.layers.tangent[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *elem = layer_data[mlt->tri[t]];
|
2017-05-14 16:13:00 +02:00
|
|
|
#ifdef USE_COMP_MESH_DATA
|
2017-06-30 18:01:20 +10:00
|
|
|
normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
|
2017-05-14 16:13:00 +02:00
|
|
|
#else
|
2017-06-30 18:01:20 +10:00
|
|
|
copy_v3_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
|
2017-05-14 16:13:00 +02:00
|
|
|
#endif
|
2017-06-30 18:01:20 +10:00
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
|
|
|
/* VCOLs */
|
2017-06-30 18:01:20 +10:00
|
|
|
for (uint j = 0; j < vcol_len; j++) {
|
|
|
|
const MLoopCol *layer_data = rdata->cd.layers.vcol[j];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const uchar *elem = &layer_data[mlt->tri[t]].r;
|
|
|
|
copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
}
|
2017-06-30 18:01:20 +10:00
|
|
|
}
|
|
|
|
}
|
2017-05-01 17:58:15 +02:00
|
|
|
|
2017-06-30 18:01:20 +10:00
|
|
|
vbo_len_used = GWN_vertbuf_raw_used(&layers_combined_step[0]);
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
/* Check all layers are write aligned. */
|
|
|
|
if (layers_combined_len > 1) {
|
|
|
|
for (uint i = 1; i < layers_combined_len; i++) {
|
|
|
|
BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&layers_combined_step[i]));
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-30 18:01:20 +10:00
|
|
|
#endif
|
2017-04-25 18:46:59 +02:00
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
2017-05-22 16:20:54 +10:00
|
|
|
|
|
|
|
#undef USE_COMP_MESH_DATA
|
|
|
|
|
2017-04-25 18:46:59 +02:00
|
|
|
return cache->shaded_triangles_data;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
|
2017-05-22 23:31:46 +10:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV));
|
|
|
|
|
|
|
|
if (cache->tri_aligned_uv == NULL) {
|
2018-05-11 07:48:52 +02:00
|
|
|
uint vidx = 0;
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-22 23:31:46 +10:00
|
|
|
static struct { uint uv; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.uv = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = cache->tri_aligned_uv = GWN_vertbuf_create_with_format(&format);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
|
|
|
const MLoopUV *mloopuv = rdata->mloopuv;
|
|
|
|
|
2018-05-15 08:56:45 +02:00
|
|
|
BMEditMesh *embm = rdata->edit_bmesh;
|
|
|
|
/* get uv's from active UVMap */
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
/* edit mode */
|
|
|
|
BMesh *bm = embm->bm;
|
|
|
|
|
|
|
|
const int layer_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
|
|
|
|
for (uint i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **bm_looptri = (const BMLoop **)embm->looptris[i];
|
|
|
|
if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const BMLoop *loop = bm_looptri[t];
|
|
|
|
const int index = BM_elem_index_get(loop);
|
|
|
|
if (index != -1) {
|
|
|
|
const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* object mode */
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
|
|
|
|
}
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
2018-05-15 08:56:45 +02:00
|
|
|
|
2017-05-22 23:31:46 +10:00
|
|
|
vbo_len_used = vidx;
|
|
|
|
|
|
|
|
BLI_assert(vbo_len_capacity == vbo_len_used);
|
2017-06-29 15:46:00 +02:00
|
|
|
UNUSED_VARS_NDEBUG(vbo_len_used);
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->tri_aligned_uv;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
|
2017-05-17 16:01:18 +10:00
|
|
|
MeshRenderData *rdata, const bool use_hide,
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf **r_vbo)
|
2017-03-09 01:29:58 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
2017-03-09 01:29:58 +01:00
|
|
|
|
2017-05-17 16:01:18 +10:00
|
|
|
if (*r_vbo == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, nor; } attr_id;
|
2017-03-09 01:29:58 +01:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
2017-03-09 01:29:58 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = *r_vbo = GWN_vertbuf_create_with_format(&format);
|
2017-03-09 01:29:58 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-19 00:10:32 +10:00
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
Gwn_VertBufRaw pos_step, nor_step;
|
|
|
|
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
|
|
|
|
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
|
2017-03-09 01:29:58 +01:00
|
|
|
|
2017-11-06 14:14:07 -02:00
|
|
|
float (*lnors)[3] = rdata->loop_normals;
|
|
|
|
|
2017-06-29 20:11:16 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
2017-11-06 14:14:07 -02:00
|
|
|
Gwn_PackedNormal *pnors_pack, *vnors_pack;
|
|
|
|
|
|
|
|
if (lnors == NULL) {
|
|
|
|
mesh_render_data_ensure_poly_normals_pack(rdata);
|
|
|
|
mesh_render_data_ensure_vert_normals_pack(rdata);
|
2017-06-29 20:11:16 +10:00
|
|
|
|
2017-11-06 14:14:07 -02:00
|
|
|
pnors_pack = rdata->poly_normals_pack;
|
|
|
|
vnors_pack = rdata->vert_normals_pack;
|
|
|
|
}
|
2017-06-29 20:11:16 +10:00
|
|
|
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
|
|
|
const BMFace *bm_face = bm_looptri[0]->f;
|
|
|
|
|
|
|
|
/* use_hide always for edit-mode */
|
|
|
|
if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-11-06 14:14:07 -02:00
|
|
|
if (lnors) {
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
|
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
|
2017-06-29 20:11:16 +10:00
|
|
|
for (uint t = 0; t < 3; t++) {
|
2017-11-06 14:14:07 -02:00
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
|
2017-06-29 20:11:16 +10:00
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
|
|
|
else {
|
2017-06-29 20:11:16 +10:00
|
|
|
const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack;
|
|
|
|
}
|
|
|
|
}
|
2017-05-21 15:59:34 -04:00
|
|
|
|
2018-04-19 11:03:58 +02:00
|
|
|
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
|
|
|
|
if (rdata->edit_data && rdata->edit_data->vertexCos) {
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
int vidx = BM_elem_index_get(bm_looptri[t]->v);
|
|
|
|
const float *pos = rdata->edit_data->vertexCos[vidx];
|
|
|
|
copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
|
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-06-29 20:11:16 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-10-31 15:15:14 -02:00
|
|
|
if (lnors == NULL) {
|
|
|
|
/* Use normals from vertex. */
|
|
|
|
mesh_render_data_ensure_poly_normals_pack(rdata);
|
|
|
|
}
|
2017-06-29 20:11:16 +10:00
|
|
|
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
|
|
|
const MPoly *mp = &rdata->mpoly[mlt->poly];
|
|
|
|
|
|
|
|
if (use_hide && (mp->flag & ME_HIDE)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint vtri[3] = {
|
|
|
|
rdata->mloop[mlt->tri[0]].v,
|
|
|
|
rdata->mloop[mlt->tri[1]].v,
|
|
|
|
rdata->mloop[mlt->tri[2]].v,
|
|
|
|
};
|
|
|
|
|
2017-10-31 15:15:14 -02:00
|
|
|
if (lnors) {
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const float *nor = lnors[mlt->tri[t]];
|
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mp->flag & ME_SMOOTH) {
|
2017-06-29 20:11:16 +10:00
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const MVert *mv = &rdata->mvert[vtri[t]];
|
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_s3(mv->no);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const Gwn_PackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *pnors_pack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint t = 0; t < 3; t++) {
|
|
|
|
const MVert *mv = &rdata->mvert[vtri[t]];
|
|
|
|
copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), mv->co);
|
|
|
|
}
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-06-29 20:11:16 +10:00
|
|
|
|
|
|
|
vbo_len_used = GWN_vertbuf_raw_used(&pos_step);
|
|
|
|
BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&nor_step));
|
2017-03-09 01:29:58 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
|
|
|
}
|
2017-05-17 16:01:18 +10:00
|
|
|
return *r_vbo;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals(
|
2017-05-17 16:01:18 +10:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
return mesh_batch_cache_get_tri_pos_and_normals_ex(
|
|
|
|
rdata, false,
|
|
|
|
&cache->pos_with_normals);
|
|
|
|
}
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_tri_pos_and_normals_visible_only(
|
|
|
|
MeshRenderData *rdata)
|
2017-05-17 16:01:18 +10:00
|
|
|
{
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo_dummy = NULL;
|
2017-05-17 16:01:18 +10:00
|
|
|
return mesh_batch_cache_get_tri_pos_and_normals_ex(
|
|
|
|
rdata, true,
|
2017-08-16 17:47:58 +10:00
|
|
|
&vbo_dummy);
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
|
|
|
|
|
|
|
if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) {
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, data; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
|
|
|
|
int vidx = 0;
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
for (int i = 0; i < vbo_len_capacity; ++i) {
|
|
|
|
float pcenter[3], pnor[3];
|
|
|
|
bool selected = false;
|
|
|
|
|
|
|
|
if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) {
|
|
|
|
|
|
|
|
Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 };
|
|
|
|
nor = GWN_normal_convert_i10_v3(pnor);
|
|
|
|
nor.w = selected ? 1 : 0;
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
|
|
|
|
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
|
|
|
|
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const int vbo_len_used = vidx;
|
2018-01-17 19:54:13 +11:00
|
|
|
BLI_assert(vbo_len_used <= vbo_len_capacity);
|
2017-08-17 01:38:07 +10:00
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_fcenter_pos_with_nor_and_sel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
|
|
|
|
|
|
|
|
if (cache->ed_edge_pos == NULL) {
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, data; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
|
|
|
|
int vidx = 0;
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo = cache->ed_edge_pos = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMEdge *eed;
|
|
|
|
|
|
|
|
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co);
|
|
|
|
vidx += 1;
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* not yet done! */
|
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
const int vbo_len_used = vidx;
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
UNUSED_VARS_NDEBUG(vbo_len_used);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_edge_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_vert_pos == NULL) {
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, data; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
|
|
|
|
uint vidx = 0;
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo = cache->ed_vert_pos = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMVert *eve;
|
|
|
|
|
|
|
|
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-08-17 07:13:02 +10:00
|
|
|
for (int i = 0; i < vbo_len_capacity; i++) {
|
|
|
|
const MVert *mv = &rdata->mvert[i];
|
|
|
|
if (!(mv->flag & ME_HIDE)) {
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
}
|
2017-08-17 01:38:07 +10:00
|
|
|
}
|
|
|
|
const uint vbo_len_used = vidx;
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
|
|
|
|
UNUSED_VARS_NDEBUG(vbo_len_used);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_vert_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Gwn_VertBuf *mesh_create_facedot_select_id(
|
|
|
|
MeshRenderData *rdata, uint select_id_offset)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, col; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
|
|
|
|
int vidx = 0;
|
|
|
|
|
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
uint select_index = select_id_offset;
|
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMEdge *efa;
|
|
|
|
|
|
|
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
|
|
|
int select_id;
|
|
|
|
GPU_select_index_get(select_index, &select_id);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
select_index += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* not yet done! */
|
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
const int vbo_len_used = vidx;
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vbo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Gwn_VertBuf *mesh_create_edges_select_id(
|
|
|
|
MeshRenderData *rdata, uint select_id_offset)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, col; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
|
|
|
|
int vidx = 0;
|
|
|
|
|
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
uint select_index = select_id_offset;
|
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMEdge *eed;
|
|
|
|
|
|
|
|
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
|
|
|
int select_id;
|
|
|
|
GPU_select_index_get(select_index, &select_id);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
|
|
|
|
vidx += 1;
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
select_index += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* not yet done! */
|
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
const int vbo_len_used = vidx;
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vbo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Gwn_VertBuf *mesh_create_verts_select_id(
|
|
|
|
MeshRenderData *rdata, uint select_id_offset)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
|
|
|
static Gwn_VertFormat format = { 0 };
|
|
|
|
static struct { uint pos, col; } attr_id;
|
|
|
|
if (format.attrib_ct == 0) {
|
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
|
|
|
|
int vidx = 0;
|
|
|
|
|
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
|
|
|
uint select_index = select_id_offset;
|
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMVert *eve;
|
|
|
|
|
|
|
|
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
|
|
|
int select_id;
|
|
|
|
GPU_select_index_get(select_index, &select_id);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
select_index += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-08-17 07:13:02 +10:00
|
|
|
for (int i = 0; i < vbo_len_capacity; i++) {
|
|
|
|
const MVert *mv = &rdata->mvert[i];
|
|
|
|
if (!(mv->flag & ME_HIDE)) {
|
|
|
|
int select_id;
|
|
|
|
GPU_select_index_get(select_index, &select_id);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
|
|
|
|
vidx += 1;
|
|
|
|
}
|
|
|
|
select_index += 1;
|
|
|
|
}
|
2017-08-17 01:38:07 +10:00
|
|
|
}
|
|
|
|
const int vbo_len_used = vidx;
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vbo;
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_tri_weights(
|
|
|
|
MeshRenderData *rdata, bool use_hide, int defgroup)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
2017-05-04 03:35:01 +10:00
|
|
|
BLI_assert(
|
|
|
|
rdata->types &
|
|
|
|
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT));
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
2018-05-11 07:48:52 +02:00
|
|
|
uint cidx = 0;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint col; } attr_id;
|
2017-05-03 18:55:40 +02:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
2017-05-03 18:55:40 +02:00
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
mesh_render_data_ensure_vert_weight_color(rdata, defgroup);
|
|
|
|
const float (*vert_weight_color)[3] = rdata->vert_weight_color;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
2017-05-17 16:01:18 +10:00
|
|
|
/* Assume 'use_hide' */
|
2017-05-17 11:28:44 +10:00
|
|
|
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
|
|
|
const int v_index = BM_elem_index_get(ltri[tri_corner]->v);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
2017-05-17 16:01:18 +10:00
|
|
|
if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
|
|
|
const uint v_index = rdata->mloop[mlt->tri[tri_corner]].v;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
|
2017-05-17 16:01:18 +10:00
|
|
|
}
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
2017-05-08 16:25:29 +10:00
|
|
|
vbo_len_used = cidx;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
return vbo;
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_tri_vert_colors(
|
|
|
|
MeshRenderData *rdata, bool use_hide)
|
2017-05-04 19:59:27 +02:00
|
|
|
{
|
|
|
|
BLI_assert(
|
|
|
|
rdata->types &
|
|
|
|
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL));
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
2018-05-11 07:48:52 +02:00
|
|
|
uint cidx = 0;
|
2017-05-04 19:59:27 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint col; } attr_id;
|
2017-05-04 19:59:27 +02:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-05-04 19:59:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
2017-05-04 19:59:27 +02:00
|
|
|
|
2017-05-08 16:25:29 +10:00
|
|
|
const uint vbo_len_capacity = tri_len * 3;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-04 19:59:27 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
mesh_render_data_ensure_vert_color(rdata);
|
|
|
|
const char (*vert_color)[3] = rdata->vert_color;
|
2017-05-04 19:59:27 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
2017-05-17 16:01:18 +10:00
|
|
|
/* Assume 'use_hide' */
|
2017-05-17 11:28:44 +10:00
|
|
|
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-05-17 17:14:10 +10:00
|
|
|
const int l_index = BM_elem_index_get(ltri[tri_corner]);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
2017-05-17 16:01:18 +10:00
|
|
|
if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-05-17 17:14:10 +10:00
|
|
|
const uint l_index = mlt->tri[tri_corner];
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
|
2017-05-17 16:01:18 +10:00
|
|
|
}
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-05-04 19:59:27 +02:00
|
|
|
}
|
|
|
|
}
|
2017-05-08 16:25:29 +10:00
|
|
|
const uint vbo_len_used = cidx;
|
2017-05-04 19:59:27 +02:00
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-05-04 19:59:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
return vbo;
|
2017-05-04 19:59:27 +02:00
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_tri_select_id(
|
2017-08-17 01:38:07 +10:00
|
|
|
MeshRenderData *rdata, bool use_hide, uint select_id_offset)
|
2017-05-05 05:17:31 +10:00
|
|
|
{
|
|
|
|
BLI_assert(
|
|
|
|
rdata->types &
|
|
|
|
(MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
2018-05-11 07:48:52 +02:00
|
|
|
uint cidx = 0;
|
2017-05-05 05:17:31 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint col; } attr_id;
|
2017-05-05 05:17:31 +10:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
|
2017-05-05 05:17:31 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
2017-05-05 05:17:31 +10:00
|
|
|
|
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-05 05:17:31 +10:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
2017-05-17 16:01:18 +10:00
|
|
|
/* Assume 'use_hide' */
|
|
|
|
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
|
2017-05-17 11:28:44 +10:00
|
|
|
const int poly_index = BM_elem_index_get(ltri[0]->f);
|
|
|
|
int select_id;
|
2017-08-17 01:38:07 +10:00
|
|
|
GPU_select_index_get(poly_index + select_id_offset, &select_id);
|
2017-05-17 11:28:44 +10:00
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
|
|
|
const int poly_index = mlt->poly;
|
|
|
|
if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) {
|
|
|
|
int select_id;
|
2017-08-17 01:38:07 +10:00
|
|
|
GPU_select_index_get(poly_index + select_id_offset, &select_id);
|
2017-05-17 11:28:44 +10:00
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
2017-05-05 05:17:31 +10:00
|
|
|
}
|
|
|
|
}
|
2017-05-08 16:25:29 +10:00
|
|
|
vbo_len_used = cidx;
|
2017-05-05 05:17:31 +10:00
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-05-05 05:17:31 +10:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 17:47:58 +10:00
|
|
|
return vbo;
|
2017-05-05 05:17:31 +10:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
|
2017-05-05 05:41:30 +10:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
2017-02-23 11:54:40 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
if (cache->pos_in_order == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, nor; } attr_id;
|
2017-01-25 09:16:29 +01:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format);
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-17 11:28:44 +10:00
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter iter;
|
|
|
|
BMVert *eve;
|
|
|
|
uint i;
|
|
|
|
|
|
|
|
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
|
|
|
static short no_short[3];
|
|
|
|
normal_float_to_short_v3(no_short, eve->no);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
BLI_assert(i == vbo_len_capacity);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < vbo_len_capacity; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->pos_in_order;
|
|
|
|
}
|
|
|
|
|
2018-05-11 07:48:52 +02:00
|
|
|
static Gwn_VertFormat *edit_mesh_overlay_pos_format(uint *r_pos_id)
|
2017-05-13 16:45:06 +02:00
|
|
|
{
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format_pos = { 0 };
|
2017-05-13 16:45:06 +02:00
|
|
|
static unsigned pos_id;
|
|
|
|
if (format_pos.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
pos_id = GWN_vertformat_attr_add(&format_pos, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
*r_pos_id = pos_id;
|
|
|
|
return &format_pos;
|
|
|
|
}
|
|
|
|
|
2018-05-11 07:48:52 +02:00
|
|
|
static Gwn_VertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lnor_id)
|
2017-05-13 16:45:06 +02:00
|
|
|
{
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format_nor = { 0 };
|
|
|
|
static Gwn_VertFormat format_nor_loop = { 0 };
|
2017-05-13 16:45:06 +02:00
|
|
|
static unsigned vnor_id, vnor_loop_id, lnor_id;
|
|
|
|
if (format_nor.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
vnor_id = GWN_vertformat_attr_add(&format_nor, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
|
|
|
vnor_loop_id = GWN_vertformat_attr_add(&format_nor_loop, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
|
|
|
lnor_id = GWN_vertformat_attr_add(&format_nor_loop, "lnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (r_lnor_id) {
|
|
|
|
*r_vnor_id = vnor_loop_id;
|
|
|
|
*r_lnor_id = lnor_id;
|
|
|
|
return &format_nor_loop;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*r_vnor_id = vnor_id;
|
|
|
|
return &format_nor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-11 07:48:52 +02:00
|
|
|
static Gwn_VertFormat *edit_mesh_overlay_data_format(uint *r_data_id)
|
2017-05-13 16:45:06 +02:00
|
|
|
{
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format_flag = { 0 };
|
2017-05-13 16:45:06 +02:00
|
|
|
static unsigned data_id;
|
|
|
|
if (format_flag.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
data_id = GWN_vertformat_attr_add(&format_flag, "data", GWN_COMP_U8, 4, GWN_FETCH_INT);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
*r_data_id = data_id;
|
|
|
|
return &format_flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_batch_cache_create_overlay_tri_buffers(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
|
|
|
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
|
|
|
const int vbo_len_capacity = tri_len * 3;
|
|
|
|
int vbo_len_used = 0;
|
|
|
|
|
|
|
|
/* Positions */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_pos = NULL;
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, vnor, lnor, data; } attr_id;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_tri_pos == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_pos = cache->ed_tri_pos =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Normals */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_nor = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_tri_nor == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_nor = cache->ed_tri_nor =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Data */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_data = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_tri_data == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_data = cache->ed_tri_data =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
|
|
|
if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
|
2017-05-13 16:45:06 +02:00
|
|
|
add_overlay_tri(
|
|
|
|
rdata, vbo_pos, vbo_nor, vbo_data,
|
2017-05-17 12:22:22 +10:00
|
|
|
attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
|
2017-05-24 11:43:55 +10:00
|
|
|
bm_looptri, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
|
|
|
|
vbo_len_used += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finish */
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
if (vbo_pos != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_nor != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_data != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_batch_cache_create_overlay_ledge_buffers(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
|
|
|
|
|
|
|
const int ledge_len = mesh_render_data_loose_edges_len_get(rdata);
|
|
|
|
|
|
|
|
const int vbo_len_capacity = ledge_len * 2;
|
|
|
|
int vbo_len_used = 0;
|
|
|
|
|
|
|
|
/* Positions */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_pos = NULL;
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, vnor, data; } attr_id;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_ledge_pos == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_pos = cache->ed_ledge_pos =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Normals */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_nor = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_ledge_nor == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_nor = cache->ed_ledge_nor =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Data */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_data = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_ledge_data == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_data = cache->ed_ledge_data =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
for (uint i = 0; i < ledge_len; i++) {
|
2017-05-24 13:33:48 +10:00
|
|
|
const BMEdge *eed = BM_edge_at_index(bm, rdata->loose_edges[i]);
|
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
2017-05-24 11:43:55 +10:00
|
|
|
add_overlay_loose_edge(
|
|
|
|
rdata, vbo_pos, vbo_nor, vbo_data,
|
|
|
|
attr_id.pos, attr_id.vnor, attr_id.data,
|
2017-05-24 13:33:48 +10:00
|
|
|
eed, vbo_len_used);
|
2017-05-24 11:43:55 +10:00
|
|
|
vbo_len_used += 2;
|
|
|
|
}
|
|
|
|
}
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Finish */
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
if (vbo_pos != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_nor != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_data != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_batch_cache_create_overlay_lvert_buffers(
|
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
2017-05-13 16:45:06 +02:00
|
|
|
const int lvert_len = mesh_render_data_loose_verts_len_get(rdata);
|
|
|
|
|
|
|
|
const int vbo_len_capacity = lvert_len;
|
|
|
|
int vbo_len_used = 0;
|
|
|
|
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, vnor, data; } attr_id;
|
|
|
|
|
2017-05-13 16:45:06 +02:00
|
|
|
/* Positions */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_pos = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_lvert_pos == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_pos = cache->ed_lvert_pos =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Normals */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_nor = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_lvert_nor == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_nor = cache->ed_lvert_nor =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Data */
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_data = NULL;
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->ed_lvert_data == NULL) {
|
2017-05-17 12:22:22 +10:00
|
|
|
vbo_data = cache->ed_lvert_data =
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
|
|
|
|
GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
2017-05-24 11:43:55 +10:00
|
|
|
for (uint i = 0; i < lvert_len; i++) {
|
2017-05-24 13:33:48 +10:00
|
|
|
BMVert *eve = BM_vert_at_index(bm, rdata->loose_verts[i]);
|
2017-05-13 16:45:06 +02:00
|
|
|
add_overlay_loose_vert(
|
|
|
|
rdata, vbo_pos, vbo_nor, vbo_data,
|
2017-05-17 12:22:22 +10:00
|
|
|
attr_id.pos, attr_id.vnor, attr_id.data,
|
2017-05-24 13:33:48 +10:00
|
|
|
eve, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
vbo_len_used += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finish */
|
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
|
|
|
if (vbo_pos != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_nor != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
if (vbo_data != NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Position */
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_pos(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_tri_pos == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_tri_pos;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_pos(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_ledge_pos == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_ledge_pos;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_pos(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_lvert_pos == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_lvert_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Normal */
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_nor(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_tri_nor == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_tri_nor;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_nor(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_ledge_nor == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_ledge_nor;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_nor(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_lvert_nor == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_lvert_nor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Data */
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_data(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_tri_data == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_tri_data;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_data(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_ledge_data == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_ledge_data;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_data(
|
2017-05-13 16:45:06 +02:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
if (cache->ed_lvert_data == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->ed_lvert_data;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
if (cache->edges_in_order == NULL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
|
|
|
const int edge_len = mesh_render_data_edges_len_get(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
|
2017-05-24 11:43:55 +10:00
|
|
|
|
|
|
|
BLI_assert(rdata->types & MR_DATATYPE_EDGE);
|
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter eiter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMEdge *eed;
|
|
|
|
BM_ITER_MESH(eed, &eiter, bm, BM_EDGES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
|
2017-05-24 11:43:55 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const MEdge *ed = rdata->medge;
|
|
|
|
for (int i = 0; i < edge_len; i++, ed++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_line_verts(&elb, ed->v1, ed->v2);
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->edges_in_order = GWN_indexbuf_build(&elb);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->edges_in_order;
|
|
|
|
}
|
|
|
|
|
2018-05-19 13:31:44 +02:00
|
|
|
#define NO_EDGE INT_MAX
|
|
|
|
static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, MeshBatchCache *cache)
|
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
|
|
|
|
|
|
|
|
if (cache->edges_adjacency == NULL) {
|
|
|
|
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
2018-05-21 13:21:26 +02:00
|
|
|
cache->is_manifold = true;
|
|
|
|
|
2018-05-19 13:31:44 +02:00
|
|
|
/* Allocate max but only used indices are sent to GPU. */
|
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, tri_len * 3, vert_len);
|
|
|
|
|
|
|
|
EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3);
|
|
|
|
/* Create edges for each pair of triangles sharing an edge. */
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
|
|
for (int e = 0; e < 3; ++e) {
|
2018-05-30 19:45:03 +02:00
|
|
|
uint v0, v1, v2;
|
2018-05-19 13:31:44 +02:00
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
|
|
|
if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
v0 = BM_elem_index_get(bm_looptri[e]->v);
|
2018-05-22 07:31:11 +02:00
|
|
|
v1 = BM_elem_index_get(bm_looptri[(e + 1) % 3]->v);
|
|
|
|
v2 = BM_elem_index_get(bm_looptri[(e + 2) % 3]->v);
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
MLoop *mloop = rdata->mloop;
|
|
|
|
MLoopTri *mlt = rdata->mlooptri + i;
|
|
|
|
v0 = mloop[mlt->tri[e]].v;
|
2018-05-22 07:31:11 +02:00
|
|
|
v1 = mloop[mlt->tri[(e + 1) % 3]].v;
|
|
|
|
v2 = mloop[mlt->tri[(e + 2) % 3]].v;
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
bool inv_indices = (v1 > v2);
|
|
|
|
void **pval;
|
|
|
|
bool value_is_init = BLI_edgehash_ensure_p(eh, v1, v2, &pval);
|
|
|
|
int v_data = GET_INT_FROM_POINTER(*pval);
|
|
|
|
if (!value_is_init || v_data == NO_EDGE) {
|
|
|
|
/* Save the winding order inside the sign bit. Because the
|
|
|
|
* edgehash sort the keys and we need to compare winding later. */
|
|
|
|
int value = (int)v0 + 1; /* Int 0 cannot be signed */
|
|
|
|
*pval = SET_INT_IN_POINTER((inv_indices) ? -value : value);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */
|
|
|
|
*pval = SET_INT_IN_POINTER(NO_EDGE);
|
|
|
|
bool inv_opposite = (v_data < 0);
|
2018-05-30 19:45:03 +02:00
|
|
|
uint v_opposite = (uint)abs(v_data) - 1;
|
2018-05-19 13:31:44 +02:00
|
|
|
|
|
|
|
if (inv_opposite == inv_indices) {
|
|
|
|
/* Don't share edge if triangles have non matching winding. */
|
|
|
|
GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
|
|
|
|
GWN_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite);
|
2018-05-21 13:21:26 +02:00
|
|
|
cache->is_manifold = false;
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite);
|
|
|
|
}
|
2018-05-22 07:26:45 +02:00
|
|
|
}
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Create edges for remaning non manifold edges. */
|
|
|
|
EdgeHashIterator *ehi;
|
|
|
|
for (ehi = BLI_edgehashIterator_new(eh);
|
|
|
|
BLI_edgehashIterator_isDone(ehi) == false;
|
|
|
|
BLI_edgehashIterator_step(ehi))
|
|
|
|
{
|
2018-05-30 19:45:03 +02:00
|
|
|
uint v1, v2;
|
2018-05-19 13:31:44 +02:00
|
|
|
int v_data = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
|
|
|
|
if (v_data == NO_EDGE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
BLI_edgehashIterator_getKey(ehi, &v1, &v2);
|
2018-05-30 19:45:03 +02:00
|
|
|
uint v0 = (uint)abs(v_data) - 1;
|
2018-05-19 13:31:44 +02:00
|
|
|
if (v_data < 0) { /* inv_opposite */
|
2018-05-30 19:45:03 +02:00
|
|
|
SWAP(uint, v1, v2);
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
|
2018-05-21 13:21:26 +02:00
|
|
|
cache->is_manifold = false;
|
2018-05-19 13:31:44 +02:00
|
|
|
}
|
|
|
|
BLI_edgehashIterator_free(ehi);
|
|
|
|
BLI_edgehash_free(eh, NULL);
|
|
|
|
|
|
|
|
cache->edges_adjacency = GWN_indexbuf_build(&elb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->edges_adjacency;
|
|
|
|
|
|
|
|
}
|
|
|
|
#undef NO_EDGE
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-04-20 16:24:35 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
2017-01-25 09:16:29 +01:00
|
|
|
|
|
|
|
if (cache->triangles_in_order == NULL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
|
2017-05-17 11:28:44 +10:00
|
|
|
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
for (int i = 0; i < tri_len; ++i) {
|
|
|
|
const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
|
|
|
|
if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < tri_len; ++i) {
|
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->triangles_in_order = GWN_indexbuf_build(&elb);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->triangles_in_order;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
|
2017-05-23 17:48:05 +10:00
|
|
|
MeshRenderData *rdata, MeshBatchCache *cache)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
2017-05-23 18:23:18 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY));
|
2017-04-25 18:46:59 +02:00
|
|
|
|
|
|
|
if (cache->shaded_triangles_in_order == NULL) {
|
2017-05-23 18:23:18 +10:00
|
|
|
const int poly_len = mesh_render_data_polys_len_get(rdata);
|
2017-04-25 18:46:59 +02:00
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
2017-05-04 23:35:50 +10:00
|
|
|
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-05-04 23:35:50 +10:00
|
|
|
int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__);
|
|
|
|
cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-05-23 18:23:18 +10:00
|
|
|
/* Note that polygons (not triangles) are used here.
|
|
|
|
* This OK because result is _guaranteed_ to be the same. */
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter fiter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMFace *efa;
|
2017-05-23 18:23:18 +10:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
|
|
|
const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
|
|
|
|
mat_tri_len[ma_id] += (efa->len - 2);
|
2017-05-23 18:23:18 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (uint i = 0; i < poly_len; i++) {
|
|
|
|
const MPoly *mp = &rdata->mpoly[i]; ;
|
|
|
|
const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
|
|
|
|
mat_tri_len[ma_id] += (mp->totloop - 2);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Init ELBs. */
|
2017-05-04 23:35:50 +10:00
|
|
|
for (int i = 0; i < mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Populate ELBs. */
|
2017-05-23 18:23:18 +10:00
|
|
|
uint nidx = 0;
|
|
|
|
if (rdata->edit_bmesh) {
|
|
|
|
BMesh *bm = rdata->edit_bmesh->bm;
|
|
|
|
BMIter fiter;
|
2017-05-24 13:33:48 +10:00
|
|
|
BMFace *efa;
|
2017-05-23 18:23:18 +10:00
|
|
|
|
2017-05-24 13:33:48 +10:00
|
|
|
BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
|
|
|
|
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
|
|
|
const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
|
|
|
|
for (int j = 2; j < efa->len; j++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
|
2017-05-23 21:52:18 +10:00
|
|
|
nidx += 3;
|
|
|
|
}
|
2017-05-23 18:23:18 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (uint i = 0; i < poly_len; i++) {
|
|
|
|
const MPoly *mp = &rdata->mpoly[i]; ;
|
|
|
|
const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
|
2017-05-23 21:52:18 +10:00
|
|
|
for (int j = 2; j < mp->totloop; j++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
|
2017-05-23 21:52:18 +10:00
|
|
|
nidx += 3;
|
|
|
|
}
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Build ELBs. */
|
2017-05-04 23:35:50 +10:00
|
|
|
for (int i = 0; i < mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(mat_tri_len);
|
|
|
|
MEM_freeN(elb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->shaded_triangles_in_order;
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_edge_pos_with_sel(
|
|
|
|
MeshRenderData *rdata, bool use_wire, bool use_select_bool)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP));
|
2017-05-17 11:28:44 +10:00
|
|
|
BLI_assert(rdata->edit_bmesh == NULL);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
2018-05-11 07:48:52 +02:00
|
|
|
uint vidx = 0, cidx = 0;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, sel; } attr_id;
|
2017-05-03 18:55:40 +02:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
|
|
|
attr_id.sel = GWN_vertformat_attr_add(&format, "select", GWN_COMP_U8, 1, GWN_FETCH_INT);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const int edge_len = mesh_render_data_edges_len_get(rdata);
|
|
|
|
|
2017-10-07 15:57:14 +11:00
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
const int vbo_len_capacity = edge_len * 2;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 11:46:26 +10:00
|
|
|
if (use_select_bool) {
|
|
|
|
mesh_render_data_ensure_edge_select_bool(rdata, use_wire);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-05-17 11:46:26 +10:00
|
|
|
bool *edge_select_bool = use_select_bool ? rdata->edge_select_bool : NULL;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
for (int i = 0; i < edge_len; i++) {
|
|
|
|
const MEdge *ed = &rdata->medge[i];
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 11:28:44 +10:00
|
|
|
uchar edge_vert_sel;
|
2017-05-17 11:46:26 +10:00
|
|
|
if (use_select_bool && edge_select_bool[i]) {
|
2017-05-17 11:28:44 +10:00
|
|
|
edge_vert_sel = true;
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
2017-05-17 11:28:44 +10:00
|
|
|
else if (use_wire) {
|
|
|
|
edge_vert_sel = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
vbo_len_used = vidx;
|
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
return vbo;
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_IndexBuf *mesh_create_tri_overlay_weight_faces(
|
|
|
|
MeshRenderData *rdata)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
2017-05-17 19:21:16 +10:00
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
{
|
2017-05-17 19:21:16 +10:00
|
|
|
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
2017-05-03 18:55:40 +02:00
|
|
|
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBufBuilder elb;
|
|
|
|
GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-05-17 19:21:16 +10:00
|
|
|
for (int i = 0; i < tri_len; ++i) {
|
2017-05-17 11:28:44 +10:00
|
|
|
const MLoopTri *mlt = &rdata->mlooptri[i];
|
2017-05-17 16:41:21 +10:00
|
|
|
if (!(rdata->mpoly[mlt->poly].flag & (ME_FACE_SEL | ME_HIDE))) {
|
2017-05-17 11:28:44 +10:00
|
|
|
for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v);
|
2017-05-17 11:28:44 +10:00
|
|
|
}
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 17:47:58 +10:00
|
|
|
return GWN_indexbuf_build(&elb);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-17 18:09:40 +10:00
|
|
|
/**
|
|
|
|
* Non-edit mode vertices (only used for weight-paint mode).
|
|
|
|
*/
|
2017-08-16 17:47:58 +10:00
|
|
|
static Gwn_VertBuf *mesh_create_vert_pos_with_overlay_data(
|
|
|
|
MeshRenderData *rdata)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
BLI_assert(rdata->types & (MR_DATATYPE_VERT));
|
2017-05-17 11:28:44 +10:00
|
|
|
BLI_assert(rdata->edit_bmesh == NULL);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
Gwn_VertBuf *vbo;
|
|
|
|
{
|
2018-05-11 07:48:52 +02:00
|
|
|
uint cidx = 0;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-18 14:53:43 +10:00
|
|
|
static struct { uint data; } attr_id;
|
2017-05-03 18:55:40 +02:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_I8, 1, GWN_FETCH_INT);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const int vert_len = mesh_render_data_verts_len_get(rdata);
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
vbo = GWN_vertbuf_create_with_format(&format);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
const int vbo_len_capacity = vert_len;
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < vert_len; i++) {
|
2017-05-17 11:28:44 +10:00
|
|
|
const MVert *mv = &rdata->mvert[i];
|
2017-05-17 18:09:40 +10:00
|
|
|
const char data = mv->flag & (SELECT | ME_HIDE);
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
2017-05-18 14:53:43 +10:00
|
|
|
vbo_len_used = cidx;
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
if (vbo_len_capacity != vbo_len_used) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 17:47:58 +10:00
|
|
|
return vbo;
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** \name Public API
|
|
|
|
* \{ */
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->all_edges == NULL) {
|
|
|
|
/* create batch from Mesh */
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->all_edges = GWN_batch_create(
|
|
|
|
GWN_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
|
2017-05-04 03:35:01 +10:00
|
|
|
mesh_batch_cache_get_edges_in_order(rdata, cache));
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->all_edges;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->all_triangles == NULL) {
|
|
|
|
/* create batch from DM */
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->all_triangles = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
|
2017-05-04 03:35:01 +10:00
|
|
|
mesh_batch_cache_get_triangles_in_order(rdata, cache));
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->all_triangles;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
|
2017-02-15 13:32:35 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->triangles_with_normals == NULL) {
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-02-15 13:32:35 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->triangles_with_normals = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
|
2017-02-15 13:32:35 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-03-09 01:29:58 +01:00
|
|
|
}
|
2017-02-15 13:32:35 +01:00
|
|
|
|
2017-03-09 01:29:58 +01:00
|
|
|
return cache->triangles_with_normals;
|
|
|
|
}
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int defgroup)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->triangles_with_weights == NULL) {
|
2017-05-17 16:01:18 +10:00
|
|
|
const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->triangles_with_weights = GWN_batch_create_ex(
|
|
|
|
GWN_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, defgroup), NULL, GWN_BATCH_OWNS_VBO);
|
2017-05-17 16:01:18 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_tris = use_hide ?
|
2017-08-16 17:47:58 +10:00
|
|
|
mesh_create_tri_pos_and_normals_visible_only(rdata) :
|
2017-05-17 16:01:18 +10:00
|
|
|
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2017-05-08 16:25:29 +10:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->triangles_with_weights;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me)
|
2017-05-04 19:59:27 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->triangles_with_vert_colors == NULL) {
|
2017-05-17 16:01:18 +10:00
|
|
|
const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
|
2017-05-04 19:59:27 +02:00
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->triangles_with_vert_colors = GWN_batch_create_ex(
|
|
|
|
GWN_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GWN_BATCH_OWNS_VBO);
|
2017-05-08 16:25:29 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_tris = use_hide ?
|
2017-08-16 17:47:58 +10:00
|
|
|
mesh_create_tri_pos_and_normals_visible_only(rdata) :
|
2017-05-17 16:01:18 +10:00
|
|
|
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide);
|
2017-05-04 19:59:27 +02:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->triangles_with_vert_colors;
|
|
|
|
}
|
|
|
|
|
2017-05-05 05:17:31 +10:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(
|
|
|
|
struct Mesh *me, bool use_hide, uint select_id_offset)
|
2017-05-05 05:17:31 +10:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
if (cache->triangles_with_select_id_offset != select_id_offset) {
|
|
|
|
cache->triangles_with_select_id_offset = select_id_offset;
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
|
|
|
|
}
|
|
|
|
|
2017-05-05 05:17:31 +10:00
|
|
|
if (cache->triangles_with_select_id == NULL) {
|
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->triangles_with_select_id = GWN_batch_create_ex(
|
2017-08-17 01:38:07 +10:00
|
|
|
GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GWN_BATCH_OWNS_VBO);
|
2017-05-08 16:25:29 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo_tris = use_hide ?
|
2017-08-16 17:47:58 +10:00
|
|
|
mesh_create_tri_pos_and_normals_visible_only(rdata) :
|
2017-05-17 19:07:31 +10:00
|
|
|
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide);
|
2017-05-05 05:17:31 +10:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->triangles_with_select_id;
|
|
|
|
}
|
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
/**
|
|
|
|
* Same as #DRW_mesh_batch_cache_get_triangles_with_select_id
|
|
|
|
* without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces.
|
|
|
|
*/
|
|
|
|
struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
if (cache->triangles_with_select_mask == NULL) {
|
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
|
|
|
|
|
|
|
Gwn_VertBuf *vbo_tris = use_hide ?
|
|
|
|
mesh_create_tri_pos_and_normals_visible_only(rdata) :
|
|
|
|
mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
|
|
|
|
|
|
|
cache->triangles_with_select_mask = GWN_batch_create_ex(
|
|
|
|
GWN_PRIM_TRIS, vbo_tris, NULL, use_hide ? GWN_BATCH_OWNS_VBO : 0);
|
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->triangles_with_select_mask;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
|
2017-03-09 01:29:58 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-02-15 13:32:35 +01:00
|
|
|
|
2017-03-09 01:29:58 +01:00
|
|
|
if (cache->points_with_normals == NULL) {
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-02-15 13:32:35 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->points_with_normals = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
|
2017-02-16 16:19:48 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-02-15 13:32:35 +01:00
|
|
|
}
|
|
|
|
|
2017-03-09 01:29:58 +01:00
|
|
|
return cache->points_with_normals;
|
2017-02-15 13:32:35 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->all_verts == NULL) {
|
|
|
|
/* create batch from DM */
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->all_verts = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
|
2017-02-23 11:54:40 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return cache->all_verts;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->fancy_edges == NULL) {
|
|
|
|
/* create batch from DM */
|
2017-06-19 20:18:04 +10:00
|
|
|
static Gwn_VertFormat format = { 0 };
|
2017-05-17 12:22:22 +10:00
|
|
|
static struct { uint pos, n1, n2; } attr_id;
|
2017-01-25 09:16:29 +01:00
|
|
|
if (format.attrib_ct == 0) {
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
|
|
|
attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-05-04 03:35:01 +10:00
|
|
|
MeshRenderData *rdata = mesh_render_data_create(
|
|
|
|
me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
const int edge_len = mesh_render_data_edges_len_get(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
const int vbo_len_capacity = edge_len * 2; /* these are PRIM_LINE verts, not mesh verts */
|
|
|
|
int vbo_len_used = 0;
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
|
2017-04-19 00:10:32 +10:00
|
|
|
for (int i = 0; i < edge_len; ++i) {
|
2017-02-23 11:54:40 +01:00
|
|
|
float *vcos1, *vcos2;
|
|
|
|
float *pnor1 = NULL, *pnor2 = NULL;
|
2017-04-18 23:29:55 +10:00
|
|
|
bool is_manifold;
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
if (mesh_render_data_edge_vcos_manifold_pnors(rdata, i, &vcos1, &vcos2, &pnor1, &pnor2, &is_manifold)) {
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-29 18:52:39 +10:00
|
|
|
Gwn_PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
|
|
|
|
Gwn_PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-18 23:29:55 +10:00
|
|
|
if (is_manifold) {
|
2017-06-29 18:52:39 +10:00
|
|
|
n1value = GWN_normal_convert_i10_v3(pnor1);
|
|
|
|
n2value = GWN_normal_convert_i10_v3(pnor2);
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-29 18:52:39 +10:00
|
|
|
const Gwn_PackedNormal *n1 = &n1value;
|
|
|
|
const Gwn_PackedNormal *n2 = &n2value;
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i, vcos1);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i, n1);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i, n2);
|
2017-04-18 23:29:55 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i + 1, vcos2);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i + 1, n1);
|
|
|
|
GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i + 1, n2);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-19 00:10:32 +10:00
|
|
|
vbo_len_used += 2;
|
2017-04-18 23:29:55 +10:00
|
|
|
}
|
|
|
|
}
|
2017-04-19 00:10:32 +10:00
|
|
|
if (vbo_len_used != vbo_len_capacity) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_vertbuf_data_resize(vbo, vbo_len_used);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->fancy_edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-02-23 11:54:40 +01:00
|
|
|
return cache->fancy_edges;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2018-05-21 13:21:26 +02:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
|
2018-05-19 13:31:44 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->edge_detection == NULL) {
|
|
|
|
const int options = MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
|
|
|
|
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, options);
|
|
|
|
|
2018-05-26 10:41:25 +02:00
|
|
|
cache->edge_detection = GWN_batch_create_ex(
|
|
|
|
GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
|
|
|
|
mesh_batch_cache_get_edges_adjacency(rdata, cache), 0);
|
2018-05-19 13:31:44 +02:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
2018-05-21 13:21:26 +02:00
|
|
|
if (r_is_manifold) {
|
|
|
|
*r_is_manifold = cache->is_manifold;
|
|
|
|
}
|
|
|
|
|
2018-05-19 13:31:44 +02:00
|
|
|
return cache->edge_detection;
|
|
|
|
}
|
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
static void mesh_batch_cache_create_overlay_batches(Mesh *me)
|
2017-02-26 21:07:37 +01:00
|
|
|
{
|
2017-05-24 11:43:55 +10:00
|
|
|
BLI_assert(me->edit_btmesh != NULL);
|
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
/* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
|
2017-05-22 16:23:25 +10:00
|
|
|
const int options =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY |
|
|
|
|
MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
|
2017-02-26 21:07:37 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, options);
|
2017-03-01 14:07:04 +01:00
|
|
|
|
|
|
|
if (cache->overlay_triangles == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_triangles = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
|
2017-03-01 14:07:04 +01:00
|
|
|
}
|
2017-02-26 21:07:37 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
if (cache->overlay_loose_edges == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_loose_edges = GWN_batch_create(
|
|
|
|
GWN_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
|
2017-02-26 21:07:37 +01:00
|
|
|
}
|
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
if (cache->overlay_loose_verts == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_loose_verts = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
2017-03-01 14:07:04 +01:00
|
|
|
|
2017-05-13 16:45:06 +02:00
|
|
|
if (cache->overlay_triangles_nor == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_triangles_nor = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
|
2017-05-13 16:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cache->overlay_loose_edges_nor == NULL) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_loose_edges_nor = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
|
|
|
|
GWN_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
|
2017-02-26 21:07:37 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-02-26 21:07:37 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
2017-03-01 14:07:04 +01:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
if (cache->overlay_triangles == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_batches(me);
|
|
|
|
}
|
2017-01-25 09:16:29 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
return cache->overlay_triangles;
|
2017-02-28 14:30:34 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
|
2017-02-28 14:30:34 +01:00
|
|
|
{
|
2017-03-01 14:07:04 +01:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-02-28 14:30:34 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
if (cache->overlay_loose_edges == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_batches(me);
|
|
|
|
}
|
2017-02-28 14:30:34 +01:00
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
return cache->overlay_loose_edges;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
|
2017-01-25 09:16:29 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
if (cache->overlay_loose_verts == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_batches(me);
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-03-01 14:07:04 +01:00
|
|
|
return cache->overlay_loose_verts;
|
2017-01-25 09:16:29 +01:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
|
2017-05-13 16:45:06 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->overlay_triangles_nor == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_batches(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->overlay_triangles_nor;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
|
2017-05-13 16:45:06 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->overlay_loose_edges_nor == NULL) {
|
|
|
|
mesh_batch_cache_create_overlay_batches(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->overlay_loose_edges_nor;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
|
2017-03-02 01:07:03 +01:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->overlay_facedots == NULL) {
|
2017-04-20 16:24:35 +10:00
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
cache->overlay_facedots = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
return cache->overlay_facedots;
|
|
|
|
}
|
2017-03-02 15:03:40 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-03-02 15:03:40 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
if (cache->facedot_with_select_id_offset != select_id_offset) {
|
|
|
|
cache->facedot_with_select_id_offset = select_id_offset;
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
|
|
|
|
}
|
2017-03-02 15:03:40 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
if (cache->facedot_with_select_id == NULL) {
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
|
2017-05-08 16:16:28 +10:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
/* We only want the 'pos', not the normals or flag.
|
|
|
|
* Use since this is almost certainly already created. */
|
|
|
|
cache->facedot_with_select_id = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
|
2017-04-19 00:10:32 +10:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
GWN_batch_vertbuf_add_ex(
|
|
|
|
cache->facedot_with_select_id,
|
|
|
|
mesh_create_facedot_select_id(rdata, select_id_offset), true);
|
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->facedot_with_select_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
if (cache->edges_with_select_id_offset != select_id_offset) {
|
|
|
|
cache->edges_with_select_id_offset = select_id_offset;
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cache->edges_with_select_id == NULL) {
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
|
|
|
|
|
|
|
|
cache->edges_with_select_id = GWN_batch_create(
|
|
|
|
GWN_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL);
|
|
|
|
|
|
|
|
GWN_batch_vertbuf_add_ex(
|
|
|
|
cache->edges_with_select_id,
|
|
|
|
mesh_create_edges_select_id(rdata, select_id_offset), true);
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2017-04-20 16:24:35 +10:00
|
|
|
mesh_render_data_free(rdata);
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
|
|
|
|
2017-08-17 01:38:07 +10:00
|
|
|
return cache->edges_with_select_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset)
|
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->verts_with_select_id_offset != select_id_offset) {
|
|
|
|
cache->verts_with_select_id_offset = select_id_offset;
|
|
|
|
GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cache->verts_with_select_id == NULL) {
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
|
|
|
|
|
|
|
|
cache->verts_with_select_id = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL);
|
|
|
|
|
|
|
|
GWN_batch_vertbuf_add_ex(
|
|
|
|
cache->verts_with_select_id,
|
|
|
|
mesh_create_verts_select_id(rdata, select_id_offset), true);
|
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->verts_with_select_id;
|
2017-03-02 01:07:03 +01:00
|
|
|
}
|
|
|
|
|
2017-06-28 13:38:24 +10:00
|
|
|
Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
|
2018-05-02 15:36:09 +02:00
|
|
|
Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
|
|
|
|
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
|
2017-04-25 18:46:59 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->shaded_triangles == NULL) {
|
|
|
|
/* create batch from DM */
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI |
|
|
|
|
MR_DATATYPE_POLY | MR_DATATYPE_SHADING;
|
2017-06-28 13:38:24 +10:00
|
|
|
MeshRenderData *rdata = mesh_render_data_create_ex(me, datatype, gpumat_array, gpumat_array_len);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-05-05 11:31:42 +10:00
|
|
|
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-05-05 11:31:42 +10:00
|
|
|
cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
|
2017-04-25 18:46:59 +02:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2018-05-02 15:36:09 +02:00
|
|
|
Gwn_VertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
|
|
|
|
|
2017-05-05 11:31:42 +10:00
|
|
|
for (int i = 0; i < mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->shaded_triangles[i] = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, vbo, el[i]);
|
2017-05-15 16:12:51 +02:00
|
|
|
if (vbo_shading) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
|
2017-05-15 16:12:51 +02:00
|
|
|
}
|
2017-04-25 18:46:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
2018-05-02 15:36:09 +02:00
|
|
|
if (auto_layer_names) {
|
|
|
|
*auto_layer_names = cache->auto_layer_names;
|
|
|
|
*auto_layer_is_srgb = cache->auto_layer_is_srgb;
|
|
|
|
*auto_layer_count = cache->auto_layer_ct;
|
|
|
|
}
|
|
|
|
|
2017-04-25 18:46:59 +02:00
|
|
|
return cache->shaded_triangles;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
|
2017-05-22 23:31:46 +10:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->texpaint_triangles == NULL) {
|
|
|
|
/* create batch from DM */
|
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
|
|
|
|
|
|
|
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
|
|
|
|
|
|
|
cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2017-05-22 23:31:46 +10:00
|
|
|
for (int i = 0; i < mat_len; ++i) {
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->texpaint_triangles[i] = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, vbo, el[i]);
|
|
|
|
Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
|
2017-05-22 23:31:46 +10:00
|
|
|
if (vbo_uv) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->texpaint_triangles;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
|
2017-05-22 23:31:46 +10:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->texpaint_triangles_single == NULL) {
|
|
|
|
/* create batch from DM */
|
|
|
|
const int datatype =
|
|
|
|
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
2017-05-22 23:31:46 +10:00
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->texpaint_triangles_single = GWN_batch_create(
|
|
|
|
GWN_PRIM_TRIS, vbo, NULL);
|
|
|
|
Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
|
2017-05-22 23:31:46 +10:00
|
|
|
if (vbo_uv) {
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
|
2017-05-22 23:31:46 +10:00
|
|
|
}
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
return cache->texpaint_triangles_single;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
2017-05-05 14:25:43 +02:00
|
|
|
if (cache->overlay_paint_edges == NULL) {
|
2017-05-03 18:55:40 +02:00
|
|
|
/* create batch from Mesh */
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->overlay_paint_edges = GWN_batch_create_ex(
|
|
|
|
GWN_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GWN_BATCH_OWNS_VBO);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
2017-05-05 14:25:43 +02:00
|
|
|
return cache->overlay_paint_edges;
|
2017-05-03 18:55:40 +02:00
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->overlay_weight_faces == NULL) {
|
|
|
|
/* create batch from Mesh */
|
2017-05-04 03:35:01 +10:00
|
|
|
const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
cache->overlay_weight_faces = GWN_batch_create_ex(
|
2017-06-19 20:18:04 +10:00
|
|
|
GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
|
2017-08-16 17:47:58 +10:00
|
|
|
mesh_create_tri_overlay_weight_faces(rdata), GWN_BATCH_OWNS_INDEX);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->overlay_weight_faces;
|
|
|
|
}
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
|
2017-05-03 18:55:40 +02:00
|
|
|
{
|
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
|
|
|
|
if (cache->overlay_weight_verts == NULL) {
|
|
|
|
/* create batch from Mesh */
|
|
|
|
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
|
|
|
|
|
2017-06-19 20:18:04 +10:00
|
|
|
cache->overlay_weight_verts = GWN_batch_create(
|
|
|
|
GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
|
2017-05-03 18:55:40 +02:00
|
|
|
|
2017-08-16 17:47:58 +10:00
|
|
|
GWN_batch_vertbuf_add_ex(
|
2017-05-18 14:53:43 +10:00
|
|
|
cache->overlay_weight_verts,
|
2017-08-16 17:47:58 +10:00
|
|
|
mesh_create_vert_pos_with_overlay_data(rdata), true);
|
2017-05-03 18:55:40 +02:00
|
|
|
mesh_render_data_free(rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache->overlay_weight_verts;
|
|
|
|
}
|
|
|
|
|
2017-07-13 00:27:06 +10:00
|
|
|
/**
|
|
|
|
* Needed for when we draw with shaded data.
|
|
|
|
*/
|
|
|
|
void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
|
|
|
|
{
|
2018-05-02 15:47:45 +02:00
|
|
|
if (me->runtime.batch_cache) {
|
2017-07-13 00:27:06 +10:00
|
|
|
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
|
|
|
if (cache && cache->pos_with_normals && cache->is_sculpt_points_tag) {
|
2018-03-15 13:55:20 +01:00
|
|
|
/* XXX Force update of all the batches that contains the pos_with_normals buffer.
|
|
|
|
* TODO(fclem): Ideally, Gawain should provide a way to update a buffer without destroying it. */
|
|
|
|
mesh_batch_cache_clear_selective(me, cache->pos_with_normals);
|
|
|
|
GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
|
2017-07-13 00:27:06 +10:00
|
|
|
}
|
|
|
|
cache->is_sculpt_points_tag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-05 05:07:52 +10:00
|
|
|
/** \} */
|
|
|
|
|
2017-01-25 09:16:29 +01:00
|
|
|
#undef MESH_RENDER_FUNCTION
|