Compare commits
30 Commits
realtime-c
...
tmp-batch-
Author | SHA1 | Date | |
---|---|---|---|
a7910356b0 | |||
b65b93f5d4 | |||
ef15a45037 | |||
c3002d51f5 | |||
c4b27eb46a | |||
76963a7f64 | |||
a0ec3b7fd7 | |||
c63e45c216 | |||
04a11fa1ba | |||
a58548f6f7 | |||
6e06b4f693 | |||
e27a478a52 | |||
f0207be4df | |||
c54463b9b3 | |||
7d5e1f61bc | |||
baa34974ef | |||
711621cac4 | |||
ac0a8fbe71 | |||
f2842babc3 | |||
93f175f279 | |||
3c95a0c122 | |||
fcd7de8386 | |||
30a68e4d58 | |||
ac0d52ee4f | |||
73ca2f702f | |||
520a7ca2f3 | |||
f9e3d7d7eb | |||
e02e140ef1 | |||
a97e5be2ae | |||
7d515f8c90 |
@@ -480,6 +480,7 @@ void BKE_mesh_calc_poly_center(const struct MPoly *mpoly,
|
||||
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
|
||||
const struct MLoop *loopstart,
|
||||
const struct MVert *mvarray);
|
||||
float BKE_mesh_calc_poly_uv_area(const struct MPoly *mpoly, const struct MLoopUV *uv_array);
|
||||
void BKE_mesh_calc_poly_angles(const struct MPoly *mpoly,
|
||||
const struct MLoop *loopstart,
|
||||
const struct MVert *mvarray,
|
||||
|
@@ -2378,6 +2378,24 @@ float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const
|
||||
}
|
||||
}
|
||||
|
||||
float BKE_mesh_calc_poly_uv_area(const MPoly *mpoly, const MLoopUV *uv_array)
|
||||
{
|
||||
|
||||
int i, l_iter = mpoly->loopstart;
|
||||
float area;
|
||||
float(*vertexcos)[2] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
|
||||
|
||||
/* pack vertex cos into an array for area_poly_v2 */
|
||||
for (i = 0; i < mpoly->totloop; i++, l_iter++) {
|
||||
copy_v2_v2(vertexcos[i], uv_array[l_iter].uv);
|
||||
}
|
||||
|
||||
/* finally calculate the area */
|
||||
area = area_poly_v2((const float(*)[2])vertexcos, (unsigned int)mpoly->totloop);
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the volume and volume-weighted centroid of the volume
|
||||
* formed by the polygon and the origin.
|
||||
|
@@ -52,6 +52,7 @@ set(SRC
|
||||
intern/draw_anim_viz.c
|
||||
intern/draw_armature.c
|
||||
intern/draw_cache.c
|
||||
intern/draw_cache_extract_mesh.c
|
||||
intern/draw_cache_impl_curve.c
|
||||
intern/draw_cache_impl_displist.c
|
||||
intern/draw_cache_impl_lattice.c
|
||||
@@ -130,6 +131,7 @@ set(SRC
|
||||
DRW_engine.h
|
||||
intern/DRW_render.h
|
||||
intern/draw_cache.h
|
||||
intern/draw_cache_extract.h
|
||||
intern/draw_cache_impl.h
|
||||
intern/draw_cache_inline.h
|
||||
intern/draw_common.h
|
||||
|
@@ -4033,7 +4033,7 @@ void drw_batch_cache_validate(Object *ob)
|
||||
void drw_batch_cache_generate_requested(Object *ob)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const ToolSettings *ts = draw_ctx->scene->toolsettings;
|
||||
const Scene *scene = draw_ctx->scene;
|
||||
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
|
||||
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
||||
const bool is_paint_mode = ELEM(
|
||||
@@ -4047,13 +4047,13 @@ void drw_batch_cache_generate_requested(Object *ob)
|
||||
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, ts, is_paint_mode, use_hide);
|
||||
DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_FONT:
|
||||
case OB_SURF:
|
||||
if (mesh_eval) {
|
||||
DRW_mesh_batch_cache_create_requested(ob, mesh_eval, ts, is_paint_mode, use_hide);
|
||||
DRW_mesh_batch_cache_create_requested(ob, mesh_eval, scene, is_paint_mode, use_hide);
|
||||
}
|
||||
DRW_curve_batch_cache_create_requested(ob);
|
||||
break;
|
||||
|
244
source/blender/draw/intern/draw_cache_extract.h
Normal file
244
source/blender/draw/intern/draw_cache_extract.h
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#ifndef __DRAW_CACHE_EXTRACT_MESH_H__
|
||||
#define __DRAW_CACHE_EXTRACT_MESH_H__
|
||||
|
||||
/* Vertex Group Selection and display options */
|
||||
typedef struct DRW_MeshWeightState {
|
||||
int defgroup_active;
|
||||
int defgroup_len;
|
||||
|
||||
short flags;
|
||||
char alert_mode;
|
||||
|
||||
/* Set of all selected bones for Multipaint. */
|
||||
bool *defgroup_sel; /* [defgroup_len] */
|
||||
int defgroup_sel_count;
|
||||
} DRW_MeshWeightState;
|
||||
|
||||
/* DRW_MeshWeightState.flags */
|
||||
enum {
|
||||
DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0),
|
||||
DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1),
|
||||
};
|
||||
|
||||
typedef struct DRW_MeshCDMask {
|
||||
uint32_t uv : 8;
|
||||
uint32_t tan : 8;
|
||||
uint32_t vcol : 8;
|
||||
uint32_t orco : 1;
|
||||
uint32_t tan_orco : 1;
|
||||
} DRW_MeshCDMask;
|
||||
|
||||
typedef enum eMRIterType {
|
||||
MR_ITER_LOOPTRI = 1 << 0,
|
||||
MR_ITER_LOOP = 1 << 1,
|
||||
MR_ITER_LEDGE = 1 << 2,
|
||||
MR_ITER_LVERT = 1 << 3,
|
||||
} eMRIterType;
|
||||
|
||||
typedef enum eMRDataType {
|
||||
MR_DATA_POLY_NOR = 1 << 1,
|
||||
MR_DATA_LOOP_NOR = 1 << 2,
|
||||
MR_DATA_LOOPTRI = 1 << 3,
|
||||
} eMRDataType;
|
||||
|
||||
typedef enum eMRExtractType {
|
||||
MR_EXTRACT_BMESH,
|
||||
MR_EXTRACT_MAPPED,
|
||||
MR_EXTRACT_MESH,
|
||||
} eMRExtractType;
|
||||
|
||||
BLI_INLINE int mesh_render_mat_len_get(Mesh *me)
|
||||
{
|
||||
return MAX2(1, me->totcol);
|
||||
}
|
||||
|
||||
typedef struct MeshBufferCache {
|
||||
/* Every VBO below contains at least enough
|
||||
* data for every loops in the mesh (except fdots).
|
||||
* For some VBOs, it extends to (in this exact order) :
|
||||
* loops + loose_edges*2 + loose_verts */
|
||||
struct {
|
||||
GPUVertBuf *pos_nor; /* extend */
|
||||
GPUVertBuf *lnor; /* extend */
|
||||
GPUVertBuf *edge_fac; /* extend */
|
||||
GPUVertBuf *weights; /* extend */
|
||||
GPUVertBuf *uv_tan;
|
||||
GPUVertBuf *vcol;
|
||||
GPUVertBuf *orco;
|
||||
/* Only for edit mode. */
|
||||
GPUVertBuf *edit_data; /* extend */
|
||||
GPUVertBuf *edituv_data;
|
||||
GPUVertBuf *stretch_area;
|
||||
GPUVertBuf *stretch_angle;
|
||||
GPUVertBuf *mesh_analysis;
|
||||
GPUVertBuf *fdots_pos;
|
||||
GPUVertBuf *fdots_nor;
|
||||
GPUVertBuf *fdots_uv;
|
||||
// GPUVertBuf *fdots_edit_data; /* inside fdots_nor for now. */
|
||||
GPUVertBuf *fdots_edituv_data;
|
||||
/* Selection */
|
||||
GPUVertBuf *vert_idx; /* extend */
|
||||
GPUVertBuf *edge_idx; /* extend */
|
||||
GPUVertBuf *poly_idx;
|
||||
GPUVertBuf *fdot_idx;
|
||||
} vbo;
|
||||
/* Index Buffers:
|
||||
* Only need to be updated when topology changes. */
|
||||
struct {
|
||||
/* Indices to vloops. */
|
||||
GPUIndexBuf *tris; /* Ordered per material. */
|
||||
GPUIndexBuf *lines; /* Loose edges last. */
|
||||
GPUIndexBuf *points;
|
||||
GPUIndexBuf *fdots;
|
||||
/* 3D overlays. */
|
||||
GPUIndexBuf *lines_paint_mask; /* no loose edges. */
|
||||
GPUIndexBuf *lines_adjacency;
|
||||
/* Uv overlays. (visibility can differ from 3D view) */
|
||||
GPUIndexBuf *edituv_tris;
|
||||
GPUIndexBuf *edituv_lines;
|
||||
GPUIndexBuf *edituv_points;
|
||||
GPUIndexBuf *edituv_fdots;
|
||||
} ibo;
|
||||
} MeshBufferCache;
|
||||
|
||||
typedef enum DRWBatchFlag {
|
||||
MBC_SURFACE = (1 << 0),
|
||||
MBC_SURFACE_WEIGHTS = (1 << 1),
|
||||
MBC_EDIT_TRIANGLES = (1 << 2),
|
||||
MBC_EDIT_VERTICES = (1 << 3),
|
||||
MBC_EDIT_EDGES = (1 << 4),
|
||||
MBC_EDIT_VNOR = (1 << 5),
|
||||
MBC_EDIT_LNOR = (1 << 6),
|
||||
MBC_EDIT_FACEDOTS = (1 << 7),
|
||||
MBC_EDIT_MESH_ANALYSIS = (1 << 8),
|
||||
MBC_EDITUV_FACES_STRECH_AREA = (1 << 9),
|
||||
MBC_EDITUV_FACES_STRECH_ANGLE = (1 << 10),
|
||||
MBC_EDITUV_FACES = (1 << 11),
|
||||
MBC_EDITUV_EDGES = (1 << 12),
|
||||
MBC_EDITUV_VERTS = (1 << 13),
|
||||
MBC_EDITUV_FACEDOTS = (1 << 14),
|
||||
MBC_EDIT_SELECTION_VERTS = (1 << 15),
|
||||
MBC_EDIT_SELECTION_EDGES = (1 << 16),
|
||||
MBC_EDIT_SELECTION_FACES = (1 << 17),
|
||||
MBC_EDIT_SELECTION_FACEDOTS = (1 << 18),
|
||||
MBC_ALL_VERTS = (1 << 19),
|
||||
MBC_ALL_EDGES = (1 << 20),
|
||||
MBC_LOOSE_EDGES = (1 << 21),
|
||||
MBC_EDGE_DETECTION = (1 << 22),
|
||||
MBC_WIRE_EDGES = (1 << 23),
|
||||
MBC_WIRE_LOOPS = (1 << 24),
|
||||
MBC_WIRE_LOOPS_UVS = (1 << 25),
|
||||
MBC_SURF_PER_MAT = (1 << 26),
|
||||
} DRWBatchFlag;
|
||||
|
||||
#define MBC_EDITUV \
|
||||
(MBC_EDITUV_FACES_STRECH_AREA | MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | \
|
||||
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
|
||||
|
||||
#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \
|
||||
for (MeshBufferCache *mbc = &batch_cache->final; \
|
||||
mbc == &batch_cache->final || mbc == &batch_cache->cage; \
|
||||
mbc = (mbc == &batch_cache->final) ? &batch_cache->cage : NULL)
|
||||
|
||||
typedef struct MeshBatchCache {
|
||||
MeshBufferCache final, cage;
|
||||
|
||||
struct {
|
||||
/* Surfaces / Render */
|
||||
GPUBatch *surface;
|
||||
GPUBatch *surface_weights;
|
||||
/* Edit mode */
|
||||
GPUBatch *edit_triangles;
|
||||
GPUBatch *edit_vertices;
|
||||
GPUBatch *edit_edges;
|
||||
GPUBatch *edit_vnor;
|
||||
GPUBatch *edit_lnor;
|
||||
GPUBatch *edit_fdots;
|
||||
GPUBatch *edit_mesh_analysis;
|
||||
/* Edit UVs */
|
||||
GPUBatch *edituv_faces_strech_area;
|
||||
GPUBatch *edituv_faces_strech_angle;
|
||||
GPUBatch *edituv_faces;
|
||||
GPUBatch *edituv_edges;
|
||||
GPUBatch *edituv_verts;
|
||||
GPUBatch *edituv_fdots;
|
||||
/* Edit selection */
|
||||
GPUBatch *edit_selection_verts;
|
||||
GPUBatch *edit_selection_edges;
|
||||
GPUBatch *edit_selection_faces;
|
||||
GPUBatch *edit_selection_fdots;
|
||||
/* Common display / Other */
|
||||
GPUBatch *all_verts;
|
||||
GPUBatch *all_edges;
|
||||
GPUBatch *loose_edges;
|
||||
GPUBatch *edge_detection;
|
||||
GPUBatch *wire_edges; /* Individual edges with face normals. */
|
||||
GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */
|
||||
GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
|
||||
} batch;
|
||||
|
||||
GPUBatch **surface_per_mat;
|
||||
|
||||
/* arrays of bool uniform names (and value) that will be use to
|
||||
* set srgb conversion for auto attributes.*/
|
||||
char *auto_layer_names;
|
||||
int *auto_layer_is_srgb;
|
||||
int auto_layer_len;
|
||||
|
||||
DRWBatchFlag batch_requested;
|
||||
DRWBatchFlag batch_ready;
|
||||
|
||||
/* settings to determine if cache is invalid */
|
||||
int edge_len;
|
||||
int tri_len;
|
||||
int poly_len;
|
||||
int vert_len;
|
||||
int mat_len;
|
||||
bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
|
||||
bool is_editmode;
|
||||
bool is_uvsyncsel;
|
||||
|
||||
struct DRW_MeshWeightState weight_state;
|
||||
|
||||
DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time;
|
||||
|
||||
int lastmatch;
|
||||
|
||||
/* Valid only if edge_detection is up to date. */
|
||||
bool is_manifold;
|
||||
|
||||
bool no_loose_wire;
|
||||
} MeshBatchCache;
|
||||
|
||||
void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
|
||||
MeshBufferCache mbc,
|
||||
Mesh *me,
|
||||
const bool do_final,
|
||||
const bool use_subsurf_fdots,
|
||||
const DRW_MeshCDMask *cd_layer_used,
|
||||
const ToolSettings *ts,
|
||||
const bool use_hide);
|
||||
|
||||
#endif /* __DRAW_CACHE_EXTRACT_MESH_H__ */
|
3739
source/blender/draw/intern/draw_cache_extract_mesh.c
Normal file
3739
source/blender/draw/intern/draw_cache_extract_mesh.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -119,7 +119,7 @@ struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt);
|
||||
/* Mesh */
|
||||
void DRW_mesh_batch_cache_create_requested(struct Object *ob,
|
||||
struct Mesh *me,
|
||||
const struct ToolSettings *ts,
|
||||
const struct Scene *scene,
|
||||
const bool is_paint_mode,
|
||||
const bool use_hide);
|
||||
|
||||
@@ -143,6 +143,7 @@ struct GPUBatch *DRW_mesh_batch_cache_get_surface_weights(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_edges(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_vnors(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_lnors(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me);
|
||||
/* edit-mesh selection */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2772,7 +2772,7 @@ void DRW_draw_select_id_object(Scene *scene,
|
||||
if (use_faceselect && draw_facedot) {
|
||||
geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
|
||||
}
|
||||
DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me, scene, false, true);
|
||||
|
||||
draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes);
|
||||
|
||||
@@ -2824,7 +2824,7 @@ void DRW_draw_select_id_object(Scene *scene,
|
||||
((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
|
||||
|
||||
GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, scene, false, true);
|
||||
|
||||
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
||||
draw_mesh_face(geom_faces, 0, false, world_clip_planes);
|
||||
@@ -2835,7 +2835,7 @@ void DRW_draw_select_id_object(Scene *scene,
|
||||
}
|
||||
else {
|
||||
const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, scene, false, use_hide);
|
||||
|
||||
draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
|
||||
|
||||
|
@@ -727,7 +727,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
|
||||
}
|
||||
|
||||
if (vnormals_do) {
|
||||
geom = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
|
||||
geom = DRW_mesh_batch_cache_get_edit_vnors(ob->data);
|
||||
DRW_shgroup_call_no_cull(g_data->vnormals_shgrp, geom, ob);
|
||||
}
|
||||
if (lnormals_do) {
|
||||
|
@@ -488,6 +488,7 @@ static bool uv_edge_compare(const void *a, const void *b)
|
||||
|
||||
static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
@@ -554,7 +555,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
|
||||
UvElement *element;
|
||||
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit);
|
||||
uv_find_nearest_vert(depsgraph, scene, ima, obedit, co, 0.0f, &hit);
|
||||
|
||||
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
|
||||
island_index = element->island;
|
||||
|
@@ -163,13 +163,13 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
|
||||
|
||||
static void uvedit_get_batches(Object *ob,
|
||||
SpaceImage *sima,
|
||||
const ToolSettings *ts,
|
||||
const Scene *scene,
|
||||
GPUBatch **faces,
|
||||
GPUBatch **edges,
|
||||
GPUBatch **verts,
|
||||
GPUBatch **facedots)
|
||||
{
|
||||
int drawfaces = draw_uvs_face_check(ts);
|
||||
int drawfaces = draw_uvs_face_check(scene->toolsettings);
|
||||
const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
|
||||
const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
|
||||
|
||||
@@ -197,7 +197,7 @@ static void uvedit_get_batches(Object *ob,
|
||||
*faces = NULL;
|
||||
}
|
||||
|
||||
DRW_mesh_batch_cache_create_requested(ob, ob->data, ts, false, false);
|
||||
DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false);
|
||||
}
|
||||
|
||||
static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
|
||||
@@ -212,7 +212,7 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
|
||||
|
||||
DRW_mesh_batch_cache_validate(me);
|
||||
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
|
||||
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
|
||||
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false);
|
||||
|
||||
if (edges) {
|
||||
GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
|
||||
@@ -235,7 +235,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
|
||||
|
||||
DRW_mesh_batch_cache_validate(me);
|
||||
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
|
||||
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
|
||||
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false);
|
||||
|
||||
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
|
||||
GPU_batch_uniform_4fv(geom, "color", col);
|
||||
@@ -300,7 +300,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
|
||||
}
|
||||
}
|
||||
|
||||
uvedit_get_batches(eval_ob, sima, ts, &faces, &edges, &verts, &facedots);
|
||||
uvedit_get_batches(eval_ob, sima, scene, &faces, &edges, &verts, &facedots);
|
||||
|
||||
bool interpedges;
|
||||
bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
|
||||
|
@@ -57,13 +57,15 @@ typedef struct UvNearestHit {
|
||||
.dist_sq = FLT_MAX, \
|
||||
}
|
||||
|
||||
bool uv_find_nearest_vert(struct Scene *scene,
|
||||
bool uv_find_nearest_vert(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object *obedit,
|
||||
const float co[2],
|
||||
const float penalty_dist,
|
||||
struct UvNearestHit *hit_final);
|
||||
bool uv_find_nearest_vert_multi(struct Scene *scene,
|
||||
bool uv_find_nearest_vert_multi(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object **objects,
|
||||
const uint objects_len,
|
||||
@@ -71,24 +73,28 @@ bool uv_find_nearest_vert_multi(struct Scene *scene,
|
||||
const float penalty_dist,
|
||||
struct UvNearestHit *hit_final);
|
||||
|
||||
bool uv_find_nearest_edge(struct Scene *scene,
|
||||
bool uv_find_nearest_edge(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object *obedit,
|
||||
const float co[2],
|
||||
struct UvNearestHit *hit_final);
|
||||
bool uv_find_nearest_edge_multi(struct Scene *scene,
|
||||
bool uv_find_nearest_edge_multi(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object **objects,
|
||||
const uint objects_len,
|
||||
const float co[2],
|
||||
struct UvNearestHit *hit_final);
|
||||
|
||||
bool uv_find_nearest_face(struct Scene *scene,
|
||||
bool uv_find_nearest_face(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object *obedit,
|
||||
const float co[2],
|
||||
struct UvNearestHit *hit_final);
|
||||
bool uv_find_nearest_face_multi(struct Scene *scene,
|
||||
bool uv_find_nearest_face_multi(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct Object **objects,
|
||||
const uint objects_len,
|
||||
|
@@ -56,6 +56,7 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
@@ -606,6 +607,18 @@ void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset)
|
||||
mul_v2_fl(r_cent, 1.0f / (float)f->len);
|
||||
}
|
||||
|
||||
static void uv_mpoly_center(const MPoly *mpoly, const MLoopUV *mloopuv, float r_cent[2])
|
||||
{
|
||||
zero_v2(r_cent);
|
||||
|
||||
for (int i = 0; i < mpoly->totloop; i++) {
|
||||
const MLoopUV *luv = &mloopuv[mpoly->loopstart + i];
|
||||
add_v2_v2(r_cent, luv->uv);
|
||||
}
|
||||
|
||||
mul_v2_fl(r_cent, 1.0f / (float)mpoly->totloop);
|
||||
}
|
||||
|
||||
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
|
||||
{
|
||||
int i;
|
||||
@@ -753,8 +766,12 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c
|
||||
/** \name Find Nearest Elements
|
||||
* \{ */
|
||||
|
||||
bool uv_find_nearest_edge(
|
||||
Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit)
|
||||
bool uv_find_nearest_edge(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object *obedit,
|
||||
const float co[2],
|
||||
UvNearestHit *hit)
|
||||
{
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMFace *efa;
|
||||
@@ -766,35 +783,85 @@ bool uv_find_nearest_edge(
|
||||
|
||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||
/* (fclem) Is it garanteed that obedit_eval will be updated? */
|
||||
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
|
||||
BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
if (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
|
||||
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
||||
|
||||
const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
|
||||
|
||||
if (dist_test_sq < hit->dist_sq) {
|
||||
hit->efa = efa;
|
||||
|
||||
hit->l = l;
|
||||
hit->luv = luv;
|
||||
hit->luv_next = luv_next;
|
||||
hit->lindex = i;
|
||||
|
||||
hit->dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
|
||||
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
||||
}
|
||||
else {
|
||||
Mesh *me = em_eval->mesh_eval_cage;
|
||||
|
||||
const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE | BM_EDGE);
|
||||
|
||||
if (dist_test_sq < hit->dist_sq) {
|
||||
hit->efa = efa;
|
||||
int *p_origindex = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
|
||||
int *e_origindex = CustomData_get_layer(&me->edata, CD_ORIGINDEX);
|
||||
|
||||
hit->l = l;
|
||||
hit->luv = luv;
|
||||
hit->luv_next = luv_next;
|
||||
hit->lindex = i;
|
||||
MLoopUV *mluv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
||||
|
||||
hit->dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
MPoly *mpoly = me->mpoly;
|
||||
for (int p = 0; p < me->totpoly; p++, mpoly++) {
|
||||
if (p_origindex[p] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
efa = BM_face_at_index(em->bm, p_origindex[p]);
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < mpoly->totloop; i++) {
|
||||
MLoop *mloop = &me->mloop[mpoly->loopstart + i];
|
||||
if (e_origindex[mloop->e] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
luv = &mluv[mpoly->loopstart + i];
|
||||
luv_next = &mluv[mpoly->loopstart + ((i + 1) % mpoly->totloop)];
|
||||
const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
|
||||
|
||||
if (dist_test_sq < hit->dist_sq) {
|
||||
BMEdge *eed = BM_edge_at_index(em->bm, e_origindex[mloop->e]);
|
||||
hit->efa = efa;
|
||||
|
||||
hit->l = BM_face_edge_share_loop(efa, eed);
|
||||
hit->luv = luv;
|
||||
hit->luv_next = luv_next;
|
||||
hit->lindex = i;
|
||||
|
||||
hit->dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
bool uv_find_nearest_edge_multi(Scene *scene,
|
||||
bool uv_find_nearest_edge_multi(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object **objects,
|
||||
const uint objects_len,
|
||||
@@ -804,7 +871,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
|
||||
bool found = false;
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) {
|
||||
if (uv_find_nearest_edge(depsgraph, scene, ima, obedit, co, hit_final)) {
|
||||
hit_final->ob = obedit;
|
||||
found = true;
|
||||
}
|
||||
@@ -812,8 +879,12 @@ bool uv_find_nearest_edge_multi(Scene *scene,
|
||||
return found;
|
||||
}
|
||||
|
||||
bool uv_find_nearest_face(
|
||||
Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final)
|
||||
bool uv_find_nearest_face(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object *obedit,
|
||||
const float co[2],
|
||||
UvNearestHit *hit_final)
|
||||
{
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
bool found = false;
|
||||
@@ -823,28 +894,94 @@ bool uv_find_nearest_face(
|
||||
/* this will fill in hit.vert1 and hit.vert2 */
|
||||
float dist_sq_init = hit_final->dist_sq;
|
||||
UvNearestHit hit = *hit_final;
|
||||
if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
||||
if (uv_find_nearest_edge(depsgraph, scene, ima, obedit, co, &hit)) {
|
||||
hit.dist_sq = dist_sq_init;
|
||||
hit.l = NULL;
|
||||
hit.luv = hit.luv_next = NULL;
|
||||
|
||||
BMIter iter;
|
||||
/* (fclem) Is it garanteed that obedit_eval will be updated? */
|
||||
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
|
||||
BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
|
||||
BMFace *efa;
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
if (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||
BMIter iter;
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float cent[2];
|
||||
uv_poly_center(efa, cent, cd_loop_uv_offset);
|
||||
|
||||
const float dist_test_sq = len_squared_v2v2(co, cent);
|
||||
|
||||
if (dist_test_sq < hit.dist_sq) {
|
||||
hit.efa = efa;
|
||||
hit.dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mesh *me = em_eval->mesh_eval_cage;
|
||||
|
||||
float cent[2];
|
||||
uv_poly_center(efa, cent, cd_loop_uv_offset);
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
|
||||
|
||||
const float dist_test_sq = len_squared_v2v2(co, cent);
|
||||
int *p_origindex = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
|
||||
|
||||
if (dist_test_sq < hit.dist_sq) {
|
||||
hit.efa = efa;
|
||||
hit.dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
MLoopUV *mluv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
||||
|
||||
if (modifiers_usesSubsurfFacedots(scene, obedit)) {
|
||||
const MPoly *mpoly = me->mpoly;
|
||||
for (int p = 0; p < me->totpoly; p++, mpoly++) {
|
||||
if (p_origindex[p] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
efa = BM_face_at_index(em->bm, p_origindex[p]);
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < mpoly->totloop; i++) {
|
||||
MLoop *mloop = &me->mloop[mpoly->loopstart + i];
|
||||
MVert *mvert = &me->mvert[mloop->v];
|
||||
if ((mvert->flag & ME_VERT_FACEDOT) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const float dist_test_sq = len_squared_v2v2(co, mluv[mpoly->loopstart + i].uv);
|
||||
|
||||
if (dist_test_sq < hit.dist_sq) {
|
||||
hit.efa = efa;
|
||||
hit.dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MPoly *mpoly = me->mpoly;
|
||||
for (int p = 0; p < me->totpoly; p++, mpoly++) {
|
||||
if (p_origindex[p] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
efa = BM_face_at_index(em->bm, p_origindex[p]);
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float cent[2];
|
||||
uv_mpoly_center(mpoly, mluv, cent);
|
||||
|
||||
const float dist_test_sq = len_squared_v2v2(co, cent);
|
||||
|
||||
if (dist_test_sq < hit.dist_sq) {
|
||||
hit.efa = efa;
|
||||
hit.dist_sq = dist_test_sq;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -854,7 +991,8 @@ bool uv_find_nearest_face(
|
||||
return found;
|
||||
}
|
||||
|
||||
bool uv_find_nearest_face_multi(Scene *scene,
|
||||
bool uv_find_nearest_face_multi(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object **objects,
|
||||
const uint objects_len,
|
||||
@@ -864,7 +1002,7 @@ bool uv_find_nearest_face_multi(Scene *scene,
|
||||
bool found = false;
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) {
|
||||
if (uv_find_nearest_face(depsgraph, scene, ima, obedit, co, hit_final)) {
|
||||
hit_final->ob = obedit;
|
||||
found = true;
|
||||
}
|
||||
@@ -882,7 +1020,8 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_
|
||||
(line_point_side_v2(uv_next, uv_curr, co) <= 0.0f));
|
||||
}
|
||||
|
||||
bool uv_find_nearest_vert(Scene *scene,
|
||||
bool uv_find_nearest_vert(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object *obedit,
|
||||
float const co[2],
|
||||
@@ -894,7 +1033,7 @@ bool uv_find_nearest_vert(Scene *scene,
|
||||
/* this will fill in hit.vert1 and hit.vert2 */
|
||||
float dist_sq_init = hit_final->dist_sq;
|
||||
UvNearestHit hit = *hit_final;
|
||||
if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
||||
if (uv_find_nearest_edge(depsgraph, scene, ima, obedit, co, &hit)) {
|
||||
hit.dist_sq = dist_sq_init;
|
||||
|
||||
hit.l = NULL;
|
||||
@@ -902,46 +1041,112 @@ bool uv_find_nearest_vert(Scene *scene,
|
||||
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMFace *efa;
|
||||
BMIter iter;
|
||||
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||
/* (fclem) Is it garanteed that obedit_eval will be updated? */
|
||||
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
|
||||
BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
|
||||
|
||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
if (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||
BMIter iter;
|
||||
|
||||
BMIter liter;
|
||||
BMLoop *l;
|
||||
int i;
|
||||
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
|
||||
float dist_test_sq;
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
|
||||
dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
|
||||
dist_test_sq = SQUARE(dist_test_sq);
|
||||
}
|
||||
else {
|
||||
dist_test_sq = len_squared_v2v2(co, luv->uv);
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dist_test_sq <= hit.dist_sq) {
|
||||
if (dist_test_sq == hit.dist_sq) {
|
||||
if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
|
||||
continue;
|
||||
}
|
||||
BMIter liter;
|
||||
BMLoop *l;
|
||||
int i;
|
||||
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
|
||||
float dist_test_sq;
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||
if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
|
||||
dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
|
||||
dist_test_sq = SQUARE(dist_test_sq);
|
||||
}
|
||||
else {
|
||||
dist_test_sq = len_squared_v2v2(co, luv->uv);
|
||||
}
|
||||
|
||||
hit.dist_sq = dist_test_sq;
|
||||
if (dist_test_sq <= hit.dist_sq) {
|
||||
if (dist_test_sq == hit.dist_sq) {
|
||||
if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
hit.l = l;
|
||||
hit.luv = luv;
|
||||
hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
||||
hit.efa = efa;
|
||||
hit.lindex = i;
|
||||
found = true;
|
||||
hit.dist_sq = dist_test_sq;
|
||||
|
||||
hit.l = l;
|
||||
hit.luv = luv;
|
||||
hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
||||
hit.efa = efa;
|
||||
hit.lindex = i;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mesh *me = em_eval->mesh_eval_cage;
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE | BM_EDGE);
|
||||
|
||||
int *p_origindex = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
|
||||
int *e_origindex = CustomData_get_layer(&me->edata, CD_ORIGINDEX);
|
||||
|
||||
MLoopUV *mluv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
||||
|
||||
MPoly *mpoly = me->mpoly;
|
||||
for (int p = 0; p < me->totpoly; p++, mpoly++) {
|
||||
if (p_origindex[p] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
efa = BM_face_at_index(em->bm, p_origindex[p]);
|
||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < mpoly->totloop; i++) {
|
||||
MLoop *mloop = &me->mloop[mpoly->loopstart + i];
|
||||
if (e_origindex[mloop->e] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
MLoopUV *luv = &mluv[mpoly->loopstart + i];
|
||||
MLoopUV *luv_next = &mluv[mpoly->loopstart + ((i + 1) % mpoly->totloop)];
|
||||
|
||||
BMEdge *eed = BM_edge_at_index(em->bm, e_origindex[mloop->e]);
|
||||
BMLoop *l = BM_face_edge_share_loop(efa, eed);
|
||||
|
||||
float dist_test_sq;
|
||||
if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
|
||||
dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
|
||||
dist_test_sq = SQUARE(dist_test_sq);
|
||||
}
|
||||
else {
|
||||
dist_test_sq = len_squared_v2v2(co, luv->uv);
|
||||
}
|
||||
|
||||
if (dist_test_sq <= hit.dist_sq) {
|
||||
/* FIXME this is testing against original coord, not deformed cage. */
|
||||
if (dist_test_sq == hit.dist_sq) {
|
||||
if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
hit.dist_sq = dist_test_sq;
|
||||
|
||||
hit.l = l;
|
||||
hit.luv = luv;
|
||||
hit.luv_next = luv_next;
|
||||
hit.efa = efa;
|
||||
hit.lindex = i;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -954,7 +1159,8 @@ bool uv_find_nearest_vert(Scene *scene,
|
||||
return found;
|
||||
}
|
||||
|
||||
bool uv_find_nearest_vert_multi(Scene *scene,
|
||||
bool uv_find_nearest_vert_multi(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Image *ima,
|
||||
Object **objects,
|
||||
const uint objects_len,
|
||||
@@ -965,7 +1171,7 @@ bool uv_find_nearest_vert_multi(Scene *scene,
|
||||
bool found = false;
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) {
|
||||
if (uv_find_nearest_vert(depsgraph, scene, ima, obedit, co, penalty_dist, hit_final)) {
|
||||
hit_final->ob = obedit;
|
||||
found = true;
|
||||
}
|
||||
@@ -1274,9 +1480,9 @@ static void uv_select_linked_multi(Scene *scene,
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
|
||||
|
||||
/* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
|
||||
* this made *every* projection split the island into front/back islands.
|
||||
* Keep 'use_winding' to false, see: T50970.
|
||||
/* Note, we had 'use winding' so we don't consider overlapping islands as connected, see
|
||||
* T44320 this made *every* projection split the island into front/back islands. Keep
|
||||
* 'use_winding' to false, see: T50970.
|
||||
*
|
||||
* Better solve this by having a delimit option for select-linked operator,
|
||||
* keeping island-select working as is. */
|
||||
@@ -2513,12 +2719,12 @@ static int uv_mouse_select_multi(bContext *C,
|
||||
/* find nearest element */
|
||||
if (loop) {
|
||||
/* find edge */
|
||||
found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = uv_find_nearest_edge_multi(depsgraph, scene, ima, objects, objects_len, co, &hit);
|
||||
}
|
||||
else if (selectmode == UV_SELECT_VERTEX) {
|
||||
/* find vertex */
|
||||
found_item = uv_find_nearest_vert_multi(
|
||||
scene, ima, objects, objects_len, co, penalty_dist, &hit);
|
||||
depsgraph, scene, ima, objects, objects_len, co, penalty_dist, &hit);
|
||||
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||
|
||||
if (found_item) {
|
||||
@@ -2535,7 +2741,7 @@ static int uv_mouse_select_multi(bContext *C,
|
||||
}
|
||||
else if (selectmode == UV_SELECT_EDGE) {
|
||||
/* find edge */
|
||||
found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = uv_find_nearest_edge_multi(depsgraph, scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||
|
||||
if (found_item) {
|
||||
@@ -2554,7 +2760,7 @@ static int uv_mouse_select_multi(bContext *C,
|
||||
}
|
||||
else if (selectmode == UV_SELECT_FACE) {
|
||||
/* find face */
|
||||
found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = uv_find_nearest_face_multi(depsgraph, scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||
|
||||
if (found_item) {
|
||||
@@ -2578,7 +2784,7 @@ static int uv_mouse_select_multi(bContext *C,
|
||||
}
|
||||
}
|
||||
else if (selectmode == UV_SELECT_ISLAND) {
|
||||
found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = uv_find_nearest_edge_multi(depsgraph, scene, ima, objects, objects_len, co, &hit);
|
||||
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||
}
|
||||
|
||||
@@ -2892,6 +3098,7 @@ static void UV_OT_select_loop(wmOperatorType *ot)
|
||||
|
||||
static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
@@ -2936,7 +3143,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
|
||||
RNA_float_get_array(op->ptr, "location", co);
|
||||
}
|
||||
|
||||
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||
if (!uv_find_nearest_edge_multi(depsgraph, scene, ima, objects, objects_len, co, &hit)) {
|
||||
MEM_freeN(objects);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@@ -2550,11 +2550,13 @@ static StitchState *stitch_select(bContext *C,
|
||||
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
|
||||
if (ssc->mode == STITCH_VERT) {
|
||||
if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
|
||||
if (uv_find_nearest_vert_multi(
|
||||
depsgraph, scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
|
||||
/* Add vertex to selection, deselect all common uv's of vert other than selected and
|
||||
* update the preview. This behavior was decided so that you can do stuff like deselect
|
||||
* the opposite stitchable vertex and the initial still gets deselected */
|
||||
@@ -2575,7 +2577,8 @@ static StitchState *stitch_select(bContext *C,
|
||||
return state;
|
||||
}
|
||||
}
|
||||
else if (uv_find_nearest_edge_multi(scene, ima, ssc->objects, ssc->objects_len, co, &hit)) {
|
||||
else if (uv_find_nearest_edge_multi(
|
||||
depsgraph, scene, ima, ssc->objects, ssc->objects_len, co, &hit)) {
|
||||
/* find StitchState from hit->ob */
|
||||
StitchState *state = NULL;
|
||||
for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
|
||||
|
@@ -40,7 +40,7 @@ typedef enum {
|
||||
GPU_BATCH_READY_TO_DRAW,
|
||||
} GPUBatchPhase;
|
||||
|
||||
#define GPU_BATCH_VBO_MAX_LEN 4
|
||||
#define GPU_BATCH_VBO_MAX_LEN 5
|
||||
#define GPU_BATCH_VAO_STATIC_LEN 3
|
||||
#define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16
|
||||
|
||||
@@ -114,6 +114,7 @@ void GPU_batch_vao_cache_clear(GPUBatch *);
|
||||
void GPU_batch_callback_free_set(GPUBatch *, void (*callback)(GPUBatch *, void *), void *);
|
||||
|
||||
void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
|
||||
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo);
|
||||
|
||||
int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
|
||||
|
||||
|
@@ -36,14 +36,19 @@ typedef enum {
|
||||
} GPUIndexBufType;
|
||||
|
||||
typedef struct GPUIndexBuf {
|
||||
uint index_start;
|
||||
uint index_len;
|
||||
bool is_subrange;
|
||||
#if GPU_TRACK_INDEX_RANGE
|
||||
GPUIndexBufType index_type;
|
||||
uint32_t gl_index_type;
|
||||
uint base_index;
|
||||
#endif
|
||||
uint32_t ibo_id; /* 0 indicates not yet sent to VRAM */
|
||||
void *data; /* non-NULL indicates not yet sent to VRAM */
|
||||
union {
|
||||
void *data; /* non-NULL indicates not yet sent to VRAM */
|
||||
struct GPUIndexBuf *src; /* if is_subrange is true, this is the source buffer. */
|
||||
};
|
||||
} GPUIndexBuf;
|
||||
|
||||
void GPU_indexbuf_use(GPUIndexBuf *);
|
||||
@@ -71,9 +76,21 @@ void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2);
|
||||
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3);
|
||||
void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3, uint v4);
|
||||
|
||||
void GPU_indexbuf_set_point_vert(GPUIndexBufBuilder *builder, uint elem, uint v1);
|
||||
void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2);
|
||||
void GPU_indexbuf_set_tri_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2, uint v3);
|
||||
|
||||
/* Skip primitive rendering at the given index. */
|
||||
void GPU_indexbuf_set_point_restart(GPUIndexBufBuilder *builder, uint elem);
|
||||
void GPU_indexbuf_set_line_restart(GPUIndexBufBuilder *builder, uint elem);
|
||||
void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem);
|
||||
|
||||
GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *);
|
||||
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *);
|
||||
|
||||
/* Create a subrange of an existing indexbuffer. */
|
||||
GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *ibo, uint start, uint length);
|
||||
|
||||
void GPU_indexbuf_discard(GPUIndexBuf *);
|
||||
|
||||
int GPU_indexbuf_primitive_len(GPUPrimType prim_type);
|
||||
|
@@ -31,7 +31,7 @@
|
||||
#include "BLI_assert.h"
|
||||
|
||||
#define GPU_VERT_ATTR_MAX_LEN 16
|
||||
#define GPU_VERT_ATTR_MAX_NAMES 5
|
||||
#define GPU_VERT_ATTR_MAX_NAMES 6
|
||||
#define GPU_VERT_ATTR_NAME_AVERAGE_LEN 11
|
||||
#define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN)
|
||||
|
||||
@@ -88,6 +88,8 @@ typedef struct GPUVertFormat {
|
||||
uint packed : 1;
|
||||
/** Current offset in names[]. */
|
||||
uint name_offset : 8;
|
||||
/** Store each attrib in one contiguous buffer region. */
|
||||
uint deinterleaved : 1;
|
||||
|
||||
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
|
||||
char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
|
||||
@@ -104,6 +106,8 @@ uint GPU_vertformat_attr_add(
|
||||
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
|
||||
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
|
||||
|
||||
void GPU_vertformat_deinterleave(GPUVertFormat *format);
|
||||
|
||||
int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name);
|
||||
|
||||
BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format,
|
||||
@@ -122,7 +126,59 @@ typedef struct GPUPackedNormal {
|
||||
int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */
|
||||
} GPUPackedNormal;
|
||||
|
||||
GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]);
|
||||
GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3]);
|
||||
/* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
|
||||
* Of the code here, only struct GPUPackedNormal needs to change. */
|
||||
|
||||
#define SIGNED_INT_10_MAX 511
|
||||
#define SIGNED_INT_10_MIN -512
|
||||
|
||||
BLI_INLINE int clampi(int x, int min_allowed, int max_allowed)
|
||||
{
|
||||
#if TRUST_NO_ONE
|
||||
assert(min_allowed <= max_allowed);
|
||||
#endif
|
||||
if (x < min_allowed) {
|
||||
return min_allowed;
|
||||
}
|
||||
else if (x > max_allowed) {
|
||||
return max_allowed;
|
||||
}
|
||||
else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE int quantize(float x)
|
||||
{
|
||||
int qx = x * 511.0f;
|
||||
return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX);
|
||||
}
|
||||
|
||||
BLI_INLINE int convert_i16(short x)
|
||||
{
|
||||
/* 16-bit signed --> 10-bit signed */
|
||||
/* TODO: round? */
|
||||
return x >> 6;
|
||||
}
|
||||
|
||||
BLI_INLINE GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3])
|
||||
{
|
||||
GPUPackedNormal n = {
|
||||
.x = quantize(data[0]),
|
||||
.y = quantize(data[1]),
|
||||
.z = quantize(data[2]),
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
||||
BLI_INLINE GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3])
|
||||
{
|
||||
GPUPackedNormal n = {
|
||||
.x = convert_i16(data[0]),
|
||||
.y = convert_i16(data[1]),
|
||||
.z = convert_i16(data[2]),
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif /* __GPU_VERTEX_FORMAT_H__ */
|
||||
|
@@ -181,6 +181,25 @@ void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
|
||||
{
|
||||
BLI_assert(elem != NULL);
|
||||
/* redo the bindings */
|
||||
GPU_batch_vao_cache_clear(batch);
|
||||
|
||||
if (batch->elem != NULL && (batch->owns_flag & GPU_BATCH_OWNS_INDEX)) {
|
||||
GPU_indexbuf_discard(batch->elem);
|
||||
}
|
||||
batch->elem = elem;
|
||||
|
||||
if (own_ibo) {
|
||||
batch->owns_flag |= GPU_BATCH_OWNS_INDEX;
|
||||
}
|
||||
else {
|
||||
batch->owns_flag &= ~GPU_BATCH_OWNS_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the index of verts in the batch. */
|
||||
int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
|
||||
{
|
||||
@@ -361,13 +380,23 @@ static void create_bindings(GPUVertBuf *verts,
|
||||
const GPUVertFormat *format = &verts->format;
|
||||
|
||||
const uint attr_len = format->attr_len;
|
||||
const uint stride = format->stride;
|
||||
uint stride = format->stride;
|
||||
uint offset = 0;
|
||||
|
||||
GPU_vertbuf_use(verts);
|
||||
|
||||
for (uint a_idx = 0; a_idx < attr_len; ++a_idx) {
|
||||
const GPUVertAttr *a = &format->attrs[a_idx];
|
||||
const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride;
|
||||
|
||||
if (format->deinterleaved) {
|
||||
offset += ((a_idx == 0) ? 0 : format->attrs[a_idx - 1].sz) * verts->vertex_len;
|
||||
stride = a->sz;
|
||||
}
|
||||
else {
|
||||
offset = a->offset;
|
||||
}
|
||||
|
||||
const GLvoid *pointer = (const GLubyte *)0 + offset + v_first * stride;
|
||||
|
||||
for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
|
||||
const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
|
||||
@@ -418,8 +447,11 @@ static void create_bindings(GPUVertBuf *verts,
|
||||
|
||||
static void batch_update_program_bindings(GPUBatch *batch, uint v_first)
|
||||
{
|
||||
for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) {
|
||||
create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
|
||||
/* Reverse order so first vbos have more prevalence (in term of attrib override). */
|
||||
for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; --v) {
|
||||
if (batch->verts[v] != NULL) {
|
||||
create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
|
||||
}
|
||||
}
|
||||
if (batch->inst) {
|
||||
create_bindings(batch->inst, batch->interface, v_first, true);
|
||||
@@ -549,10 +581,10 @@ static void *elem_offset(const GPUIndexBuf *el, int v_first)
|
||||
{
|
||||
#if GPU_TRACK_INDEX_RANGE
|
||||
if (el->index_type == GPU_INDEX_U16) {
|
||||
return (GLushort *)0 + v_first;
|
||||
return (GLushort *)0 + v_first + el->index_start;
|
||||
}
|
||||
#endif
|
||||
return (GLuint *)0 + v_first;
|
||||
return (GLuint *)0 + v_first + el->index_start;
|
||||
}
|
||||
|
||||
/* Use when drawing with GPU_batch_draw_advanced */
|
||||
|
@@ -162,6 +162,100 @@ void GPU_indexbuf_add_line_adj_verts(
|
||||
GPU_indexbuf_add_generic_vert(builder, v4);
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_point_vert(GPUIndexBufBuilder *builder, uint elem, uint v1)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_POINTS);
|
||||
BLI_assert(elem < builder->max_index_len);
|
||||
builder->data[elem++] = v1;
|
||||
if (builder->index_len < elem) {
|
||||
builder->index_len = elem;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_LINES);
|
||||
BLI_assert(v1 != v2);
|
||||
BLI_assert(v1 <= builder->max_allowed_index);
|
||||
BLI_assert(v2 <= builder->max_allowed_index);
|
||||
BLI_assert((elem + 1) * 2 <= builder->max_index_len);
|
||||
uint idx = elem * 2;
|
||||
builder->data[idx++] = v1;
|
||||
builder->data[idx++] = v2;
|
||||
if (builder->index_len < idx) {
|
||||
builder->index_len = idx;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_tri_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2, uint v3)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_TRIS);
|
||||
BLI_assert(v1 != v2 && v2 != v3 && v3 != v1);
|
||||
BLI_assert(v1 <= builder->max_allowed_index);
|
||||
BLI_assert(v2 <= builder->max_allowed_index);
|
||||
BLI_assert(v3 <= builder->max_allowed_index);
|
||||
BLI_assert((elem + 1) * 3 <= builder->max_index_len);
|
||||
uint idx = elem * 3;
|
||||
builder->data[idx++] = v1;
|
||||
builder->data[idx++] = v2;
|
||||
builder->data[idx++] = v3;
|
||||
if (builder->index_len < idx) {
|
||||
builder->index_len = idx;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_point_restart(GPUIndexBufBuilder *builder, uint elem)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_POINTS);
|
||||
BLI_assert(elem < builder->max_index_len);
|
||||
builder->data[elem++] = RESTART_INDEX;
|
||||
if (builder->index_len < elem) {
|
||||
builder->index_len = elem;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_line_restart(GPUIndexBufBuilder *builder, uint elem)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_LINES);
|
||||
BLI_assert((elem + 1) * 2 <= builder->max_index_len);
|
||||
uint idx = elem * 2;
|
||||
builder->data[idx++] = RESTART_INDEX;
|
||||
builder->data[idx++] = RESTART_INDEX;
|
||||
if (builder->index_len < idx) {
|
||||
builder->index_len = idx;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem)
|
||||
{
|
||||
BLI_assert(builder->prim_type == GPU_PRIM_TRIS);
|
||||
BLI_assert((elem + 1) * 3 <= builder->max_index_len);
|
||||
uint idx = elem * 3;
|
||||
builder->data[idx++] = RESTART_INDEX;
|
||||
builder->data[idx++] = RESTART_INDEX;
|
||||
builder->data[idx++] = RESTART_INDEX;
|
||||
if (builder->index_len < idx) {
|
||||
builder->index_len = idx;
|
||||
}
|
||||
}
|
||||
|
||||
GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uint length)
|
||||
{
|
||||
GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
|
||||
BLI_assert(elem_src && !elem_src->is_subrange);
|
||||
BLI_assert(start + length <= elem_src->index_len);
|
||||
#if GPU_TRACK_INDEX_RANGE
|
||||
elem->index_type = elem_src->index_type;
|
||||
elem->gl_index_type = elem_src->gl_index_type;
|
||||
elem->base_index = elem_src->base_index;
|
||||
#endif
|
||||
elem->is_subrange = true;
|
||||
elem->src = elem_src;
|
||||
elem->index_start = start;
|
||||
elem->index_len = length;
|
||||
return elem;
|
||||
}
|
||||
|
||||
#if GPU_TRACK_INDEX_RANGE
|
||||
/* Everything remains 32 bit while building to keep things simple.
|
||||
* Find min/max after, then convert to smallest index type possible. */
|
||||
@@ -271,6 +365,10 @@ static void indexbuf_upload_data(GPUIndexBuf *elem)
|
||||
|
||||
void GPU_indexbuf_use(GPUIndexBuf *elem)
|
||||
{
|
||||
if (elem->is_subrange) {
|
||||
GPU_indexbuf_use(elem->src);
|
||||
return;
|
||||
}
|
||||
if (elem->ibo_id == 0) {
|
||||
elem->ibo_id = GPU_buf_alloc();
|
||||
}
|
||||
@@ -285,7 +383,7 @@ void GPU_indexbuf_discard(GPUIndexBuf *elem)
|
||||
if (elem->ibo_id) {
|
||||
GPU_buf_free(elem->ibo_id);
|
||||
}
|
||||
if (elem->data) {
|
||||
if (!elem->is_subrange && elem->data) {
|
||||
MEM_freeN(elem->data);
|
||||
}
|
||||
MEM_freeN(elem);
|
||||
|
@@ -216,6 +216,29 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make attribute layout non-interleaved.
|
||||
* Warning! This does not change data layout!
|
||||
* Use direct buffer access to fill the data.
|
||||
* This is for advanced usage.
|
||||
*
|
||||
* Deinterleaved data means all attrib data for each attrib
|
||||
* is stored continuously like this :
|
||||
* 000011112222
|
||||
* instead of :
|
||||
* 012012012012
|
||||
*
|
||||
* Note this is per attrib deinterleaving, NOT per component.
|
||||
* */
|
||||
void GPU_vertformat_deinterleave(GPUVertFormat *format)
|
||||
{
|
||||
/* Ideally we should change the stride and offset here. This would allow
|
||||
* us to use GPU_vertbuf_attr_set / GPU_vertbuf_attr_fill. But since
|
||||
* we use only 11 bits for attr->offset this limits the size of the
|
||||
* buffer considerably. So instead we do the conversion when creating
|
||||
* bindings in create_bindings(). */
|
||||
format->deinterleaved = true;
|
||||
}
|
||||
|
||||
uint padding(uint offset, uint alignment)
|
||||
{
|
||||
const uint mod = offset % alignment;
|
||||
@@ -389,58 +412,3 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterfa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
|
||||
* Of the code here, only struct GPUPackedNormal needs to change. */
|
||||
|
||||
#define SIGNED_INT_10_MAX 511
|
||||
#define SIGNED_INT_10_MIN -512
|
||||
|
||||
static int clampi(int x, int min_allowed, int max_allowed)
|
||||
{
|
||||
#if TRUST_NO_ONE
|
||||
assert(min_allowed <= max_allowed);
|
||||
#endif
|
||||
if (x < min_allowed) {
|
||||
return min_allowed;
|
||||
}
|
||||
else if (x > max_allowed) {
|
||||
return max_allowed;
|
||||
}
|
||||
else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
static int quantize(float x)
|
||||
{
|
||||
int qx = x * 511.0f;
|
||||
return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX);
|
||||
}
|
||||
|
||||
static int convert_i16(short x)
|
||||
{
|
||||
/* 16-bit signed --> 10-bit signed */
|
||||
/* TODO: round? */
|
||||
return x >> 6;
|
||||
}
|
||||
|
||||
GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3])
|
||||
{
|
||||
GPUPackedNormal n = {
|
||||
.x = quantize(data[0]),
|
||||
.y = quantize(data[1]),
|
||||
.z = quantize(data[2]),
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
||||
GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3])
|
||||
{
|
||||
GPUPackedNormal n = {
|
||||
.x = convert_i16(data[0]),
|
||||
.y = convert_i16(data[1]),
|
||||
.z = convert_i16(data[2]),
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#define __GPU_VERTEX_FORMAT_PRIVATE_H__
|
||||
|
||||
void VertexFormat_pack(GPUVertFormat *format);
|
||||
void VertexFormat_deinterleave(GPUVertFormat *format, uint vertex_len);
|
||||
uint padding(uint offset, uint alignment);
|
||||
uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len);
|
||||
|
||||
|
@@ -8,7 +8,7 @@ in vec2 pos;
|
||||
in float stretch;
|
||||
#else
|
||||
|
||||
in vec4 uv_adj;
|
||||
in vec2 uv_angles;
|
||||
in float angle;
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,11 @@ vec3 weight_to_rgb(float weight)
|
||||
|
||||
#define M_PI 3.1415926535897932
|
||||
|
||||
vec2 angle_to_v2(float angle)
|
||||
{
|
||||
return vec2(cos(angle), sin(angle));
|
||||
}
|
||||
|
||||
/* Adapted from BLI_math_vector.h */
|
||||
float angle_normalized_v2v2(vec2 v1, vec2 v2)
|
||||
{
|
||||
@@ -69,7 +74,9 @@ void main()
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
|
||||
|
||||
#ifdef STRETCH_ANGLE
|
||||
float uv_angle = angle_normalized_v2v2(uv_adj.xy, uv_adj.zw) / M_PI;
|
||||
vec2 v1 = angle_to_v2(uv_angles.x * M_PI);
|
||||
vec2 v2 = angle_to_v2(uv_angles.y * M_PI);
|
||||
float uv_angle = angle_normalized_v2v2(v1, v2) / M_PI;
|
||||
float stretch = 1.0 - abs(uv_angle - angle);
|
||||
stretch = stretch;
|
||||
stretch = 1.0 - stretch * stretch;
|
||||
|
Reference in New Issue
Block a user