Compare commits
30 Commits
T93558
...
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,
|
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
|
||||||
const struct MLoop *loopstart,
|
const struct MLoop *loopstart,
|
||||||
const struct MVert *mvarray);
|
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,
|
void BKE_mesh_calc_poly_angles(const struct MPoly *mpoly,
|
||||||
const struct MLoop *loopstart,
|
const struct MLoop *loopstart,
|
||||||
const struct MVert *mvarray,
|
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
|
* Calculate the volume and volume-weighted centroid of the volume
|
||||||
* formed by the polygon and the origin.
|
* formed by the polygon and the origin.
|
||||||
|
@@ -52,6 +52,7 @@ set(SRC
|
|||||||
intern/draw_anim_viz.c
|
intern/draw_anim_viz.c
|
||||||
intern/draw_armature.c
|
intern/draw_armature.c
|
||||||
intern/draw_cache.c
|
intern/draw_cache.c
|
||||||
|
intern/draw_cache_extract_mesh.c
|
||||||
intern/draw_cache_impl_curve.c
|
intern/draw_cache_impl_curve.c
|
||||||
intern/draw_cache_impl_displist.c
|
intern/draw_cache_impl_displist.c
|
||||||
intern/draw_cache_impl_lattice.c
|
intern/draw_cache_impl_lattice.c
|
||||||
@@ -130,6 +131,7 @@ set(SRC
|
|||||||
DRW_engine.h
|
DRW_engine.h
|
||||||
intern/DRW_render.h
|
intern/DRW_render.h
|
||||||
intern/draw_cache.h
|
intern/draw_cache.h
|
||||||
|
intern/draw_cache_extract.h
|
||||||
intern/draw_cache_impl.h
|
intern/draw_cache_impl.h
|
||||||
intern/draw_cache_inline.h
|
intern/draw_cache_inline.h
|
||||||
intern/draw_common.h
|
intern/draw_common.h
|
||||||
|
@@ -4033,7 +4033,7 @@ void drw_batch_cache_validate(Object *ob)
|
|||||||
void drw_batch_cache_generate_requested(Object *ob)
|
void drw_batch_cache_generate_requested(Object *ob)
|
||||||
{
|
{
|
||||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
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(
|
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
|
||||||
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
||||||
const bool is_paint_mode = ELEM(
|
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;
|
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
|
||||||
switch (ob->type) {
|
switch (ob->type) {
|
||||||
case OB_MESH:
|
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;
|
break;
|
||||||
case OB_CURVE:
|
case OB_CURVE:
|
||||||
case OB_FONT:
|
case OB_FONT:
|
||||||
case OB_SURF:
|
case OB_SURF:
|
||||||
if (mesh_eval) {
|
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);
|
DRW_curve_batch_cache_create_requested(ob);
|
||||||
break;
|
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 */
|
/* Mesh */
|
||||||
void DRW_mesh_batch_cache_create_requested(struct Object *ob,
|
void DRW_mesh_batch_cache_create_requested(struct Object *ob,
|
||||||
struct Mesh *me,
|
struct Mesh *me,
|
||||||
const struct ToolSettings *ts,
|
const struct Scene *scene,
|
||||||
const bool is_paint_mode,
|
const bool is_paint_mode,
|
||||||
const bool use_hide);
|
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_triangles(struct Mesh *me);
|
||||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(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_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_lnors(struct Mesh *me);
|
||||||
struct GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me);
|
struct GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me);
|
||||||
/* edit-mesh selection */
|
/* 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) {
|
if (use_faceselect && draw_facedot) {
|
||||||
geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
|
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);
|
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))) {
|
((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);
|
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. */
|
/* 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);
|
draw_mesh_face(geom_faces, 0, false, world_clip_planes);
|
||||||
@@ -2835,7 +2835,7 @@ void DRW_draw_select_id_object(Scene *scene,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
|
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);
|
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) {
|
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);
|
DRW_shgroup_call_no_cull(g_data->vnormals_shgrp, geom, ob);
|
||||||
}
|
}
|
||||||
if (lnormals_do) {
|
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)
|
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);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
Object *obedit = CTX_data_edit_object(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
@@ -554,7 +555,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
|
|||||||
UvElement *element;
|
UvElement *element;
|
||||||
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
||||||
Image *ima = CTX_data_edit_image(C);
|
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);
|
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
|
||||||
island_index = element->island;
|
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,
|
static void uvedit_get_batches(Object *ob,
|
||||||
SpaceImage *sima,
|
SpaceImage *sima,
|
||||||
const ToolSettings *ts,
|
const Scene *scene,
|
||||||
GPUBatch **faces,
|
GPUBatch **faces,
|
||||||
GPUBatch **edges,
|
GPUBatch **edges,
|
||||||
GPUBatch **verts,
|
GPUBatch **verts,
|
||||||
GPUBatch **facedots)
|
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_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
|
||||||
const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
|
const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ static void uvedit_get_batches(Object *ob,
|
|||||||
*faces = NULL;
|
*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),
|
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);
|
DRW_mesh_batch_cache_validate(me);
|
||||||
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(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) {
|
if (edges) {
|
||||||
GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
|
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);
|
DRW_mesh_batch_cache_validate(me);
|
||||||
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(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_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
|
||||||
GPU_batch_uniform_4fv(geom, "color", col);
|
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 interpedges;
|
||||||
bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
|
bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
|
||||||
|
@@ -57,13 +57,15 @@ typedef struct UvNearestHit {
|
|||||||
.dist_sq = FLT_MAX, \
|
.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 Image *ima,
|
||||||
struct Object *obedit,
|
struct Object *obedit,
|
||||||
const float co[2],
|
const float co[2],
|
||||||
const float penalty_dist,
|
const float penalty_dist,
|
||||||
struct UvNearestHit *hit_final);
|
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 Image *ima,
|
||||||
struct Object **objects,
|
struct Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
@@ -71,24 +73,28 @@ bool uv_find_nearest_vert_multi(struct Scene *scene,
|
|||||||
const float penalty_dist,
|
const float penalty_dist,
|
||||||
struct UvNearestHit *hit_final);
|
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 Image *ima,
|
||||||
struct Object *obedit,
|
struct Object *obedit,
|
||||||
const float co[2],
|
const float co[2],
|
||||||
struct UvNearestHit *hit_final);
|
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 Image *ima,
|
||||||
struct Object **objects,
|
struct Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
const float co[2],
|
const float co[2],
|
||||||
struct UvNearestHit *hit_final);
|
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 Image *ima,
|
||||||
struct Object *obedit,
|
struct Object *obedit,
|
||||||
const float co[2],
|
const float co[2],
|
||||||
struct UvNearestHit *hit_final);
|
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 Image *ima,
|
||||||
struct Object **objects,
|
struct Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
|
@@ -56,6 +56,7 @@
|
|||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_mesh_mapping.h"
|
#include "BKE_mesh_mapping.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
#include "BKE_node.h"
|
#include "BKE_node.h"
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_scene.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);
|
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)
|
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -753,8 +766,12 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c
|
|||||||
/** \name Find Nearest Elements
|
/** \name Find Nearest Elements
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
bool uv_find_nearest_edge(
|
bool uv_find_nearest_edge(Depsgraph *depsgraph,
|
||||||
Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit)
|
Scene *scene,
|
||||||
|
Image *ima,
|
||||||
|
Object *obedit,
|
||||||
|
const float co[2],
|
||||||
|
UvNearestHit *hit)
|
||||||
{
|
{
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMFace *efa;
|
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);
|
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 (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||||
continue;
|
|
||||||
|
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);
|
else {
|
||||||
luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
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) {
|
int *p_origindex = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
|
||||||
hit->efa = efa;
|
int *e_origindex = CustomData_get_layer(&me->edata, CD_ORIGINDEX);
|
||||||
|
|
||||||
hit->l = l;
|
MLoopUV *mluv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
||||||
hit->luv = luv;
|
|
||||||
hit->luv_next = luv_next;
|
|
||||||
hit->lindex = i;
|
|
||||||
|
|
||||||
hit->dist_sq = dist_test_sq;
|
MPoly *mpoly = me->mpoly;
|
||||||
found = true;
|
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;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uv_find_nearest_edge_multi(Scene *scene,
|
bool uv_find_nearest_edge_multi(Depsgraph *depsgraph,
|
||||||
|
Scene *scene,
|
||||||
Image *ima,
|
Image *ima,
|
||||||
Object **objects,
|
Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
@@ -804,7 +871,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
Object *obedit = objects[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;
|
hit_final->ob = obedit;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@@ -812,8 +879,12 @@ bool uv_find_nearest_edge_multi(Scene *scene,
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uv_find_nearest_face(
|
bool uv_find_nearest_face(Depsgraph *depsgraph,
|
||||||
Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final)
|
Scene *scene,
|
||||||
|
Image *ima,
|
||||||
|
Object *obedit,
|
||||||
|
const float co[2],
|
||||||
|
UvNearestHit *hit_final)
|
||||||
{
|
{
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -823,28 +894,94 @@ bool uv_find_nearest_face(
|
|||||||
/* this will fill in hit.vert1 and hit.vert2 */
|
/* this will fill in hit.vert1 and hit.vert2 */
|
||||||
float dist_sq_init = hit_final->dist_sq;
|
float dist_sq_init = hit_final->dist_sq;
|
||||||
UvNearestHit hit = *hit_final;
|
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.dist_sq = dist_sq_init;
|
||||||
hit.l = NULL;
|
hit.l = NULL;
|
||||||
hit.luv = hit.luv_next = 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;
|
BMFace *efa;
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
if (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
BMIter iter;
|
||||||
continue;
|
|
||||||
|
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];
|
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
|
||||||
uv_poly_center(efa, cent, cd_loop_uv_offset);
|
|
||||||
|
|
||||||
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) {
|
MLoopUV *mluv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
|
||||||
hit.efa = efa;
|
|
||||||
hit.dist_sq = dist_test_sq;
|
if (modifiers_usesSubsurfFacedots(scene, obedit)) {
|
||||||
found = true;
|
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;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uv_find_nearest_face_multi(Scene *scene,
|
bool uv_find_nearest_face_multi(Depsgraph *depsgraph,
|
||||||
|
Scene *scene,
|
||||||
Image *ima,
|
Image *ima,
|
||||||
Object **objects,
|
Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
@@ -864,7 +1002,7 @@ bool uv_find_nearest_face_multi(Scene *scene,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
Object *obedit = objects[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;
|
hit_final->ob = obedit;
|
||||||
found = true;
|
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));
|
(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,
|
Image *ima,
|
||||||
Object *obedit,
|
Object *obedit,
|
||||||
float const co[2],
|
float const co[2],
|
||||||
@@ -894,7 +1033,7 @@ bool uv_find_nearest_vert(Scene *scene,
|
|||||||
/* this will fill in hit.vert1 and hit.vert2 */
|
/* this will fill in hit.vert1 and hit.vert2 */
|
||||||
float dist_sq_init = hit_final->dist_sq;
|
float dist_sq_init = hit_final->dist_sq;
|
||||||
UvNearestHit hit = *hit_final;
|
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.dist_sq = dist_sq_init;
|
||||||
|
|
||||||
hit.l = NULL;
|
hit.l = NULL;
|
||||||
@@ -902,46 +1041,112 @@ bool uv_find_nearest_vert(Scene *scene,
|
|||||||
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMFace *efa;
|
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);
|
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 (!em_eval->mesh_eval_cage || em_eval->mesh_eval_cage->runtime.is_original) {
|
||||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
BMIter iter;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BMIter liter;
|
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
|
||||||
BMLoop *l;
|
|
||||||
int i;
|
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||||
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
|
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||||
float dist_test_sq;
|
continue;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dist_test_sq <= hit.dist_sq) {
|
BMIter liter;
|
||||||
if (dist_test_sq == hit.dist_sq) {
|
BMLoop *l;
|
||||||
if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
|
int i;
|
||||||
continue;
|
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.dist_sq = dist_test_sq;
|
||||||
hit.luv = luv;
|
|
||||||
hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
hit.l = l;
|
||||||
hit.efa = efa;
|
hit.luv = luv;
|
||||||
hit.lindex = i;
|
hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
|
||||||
found = true;
|
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;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uv_find_nearest_vert_multi(Scene *scene,
|
bool uv_find_nearest_vert_multi(Depsgraph *depsgraph,
|
||||||
|
Scene *scene,
|
||||||
Image *ima,
|
Image *ima,
|
||||||
Object **objects,
|
Object **objects,
|
||||||
const uint objects_len,
|
const uint objects_len,
|
||||||
@@ -965,7 +1171,7 @@ bool uv_find_nearest_vert_multi(Scene *scene,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
Object *obedit = objects[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;
|
hit_final->ob = obedit;
|
||||||
found = true;
|
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 */
|
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
|
/* Note, we had 'use winding' so we don't consider overlapping islands as connected, see
|
||||||
* this made *every* projection split the island into front/back islands.
|
* T44320 this made *every* projection split the island into front/back islands. Keep
|
||||||
* Keep 'use_winding' to false, see: T50970.
|
* 'use_winding' to false, see: T50970.
|
||||||
*
|
*
|
||||||
* Better solve this by having a delimit option for select-linked operator,
|
* Better solve this by having a delimit option for select-linked operator,
|
||||||
* keeping island-select working as is. */
|
* keeping island-select working as is. */
|
||||||
@@ -2513,12 +2719,12 @@ static int uv_mouse_select_multi(bContext *C,
|
|||||||
/* find nearest element */
|
/* find nearest element */
|
||||||
if (loop) {
|
if (loop) {
|
||||||
/* find 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);
|
||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_VERTEX) {
|
else if (selectmode == UV_SELECT_VERTEX) {
|
||||||
/* find vertex */
|
/* find vertex */
|
||||||
found_item = uv_find_nearest_vert_multi(
|
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);
|
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||||
|
|
||||||
if (found_item) {
|
if (found_item) {
|
||||||
@@ -2535,7 +2741,7 @@ static int uv_mouse_select_multi(bContext *C,
|
|||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_EDGE) {
|
else if (selectmode == UV_SELECT_EDGE) {
|
||||||
/* find 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);
|
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||||
|
|
||||||
if (found_item) {
|
if (found_item) {
|
||||||
@@ -2554,7 +2760,7 @@ static int uv_mouse_select_multi(bContext *C,
|
|||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_FACE) {
|
else if (selectmode == UV_SELECT_FACE) {
|
||||||
/* find 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);
|
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
|
||||||
|
|
||||||
if (found_item) {
|
if (found_item) {
|
||||||
@@ -2578,7 +2784,7 @@ static int uv_mouse_select_multi(bContext *C,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_ISLAND) {
|
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);
|
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)
|
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);
|
SpaceImage *sima = CTX_wm_space_image(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
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);
|
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);
|
MEM_freeN(objects);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
@@ -2550,11 +2550,13 @@ static StitchState *stitch_select(bContext *C,
|
|||||||
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
UvNearestHit hit = UV_NEAREST_HIT_INIT;
|
||||||
ARegion *ar = CTX_wm_region(C);
|
ARegion *ar = CTX_wm_region(C);
|
||||||
Image *ima = CTX_data_edit_image(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]);
|
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||||
|
|
||||||
if (ssc->mode == STITCH_VERT) {
|
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
|
/* 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
|
* 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 */
|
* the opposite stitchable vertex and the initial still gets deselected */
|
||||||
@@ -2575,7 +2577,8 @@ static StitchState *stitch_select(bContext *C,
|
|||||||
return state;
|
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 */
|
/* find StitchState from hit->ob */
|
||||||
StitchState *state = NULL;
|
StitchState *state = NULL;
|
||||||
for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
|
for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
|
||||||
|
@@ -40,7 +40,7 @@ typedef enum {
|
|||||||
GPU_BATCH_READY_TO_DRAW,
|
GPU_BATCH_READY_TO_DRAW,
|
||||||
} GPUBatchPhase;
|
} 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_STATIC_LEN 3
|
||||||
#define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16
|
#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_callback_free_set(GPUBatch *, void (*callback)(GPUBatch *, void *), void *);
|
||||||
|
|
||||||
void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
|
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);
|
int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
|
||||||
|
|
||||||
|
@@ -36,14 +36,19 @@ typedef enum {
|
|||||||
} GPUIndexBufType;
|
} GPUIndexBufType;
|
||||||
|
|
||||||
typedef struct GPUIndexBuf {
|
typedef struct GPUIndexBuf {
|
||||||
|
uint index_start;
|
||||||
uint index_len;
|
uint index_len;
|
||||||
|
bool is_subrange;
|
||||||
#if GPU_TRACK_INDEX_RANGE
|
#if GPU_TRACK_INDEX_RANGE
|
||||||
GPUIndexBufType index_type;
|
GPUIndexBufType index_type;
|
||||||
uint32_t gl_index_type;
|
uint32_t gl_index_type;
|
||||||
uint base_index;
|
uint base_index;
|
||||||
#endif
|
#endif
|
||||||
uint32_t ibo_id; /* 0 indicates not yet sent to VRAM */
|
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;
|
} GPUIndexBuf;
|
||||||
|
|
||||||
void GPU_indexbuf_use(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_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_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 *);
|
GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *);
|
||||||
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *);
|
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 *);
|
void GPU_indexbuf_discard(GPUIndexBuf *);
|
||||||
|
|
||||||
int GPU_indexbuf_primitive_len(GPUPrimType prim_type);
|
int GPU_indexbuf_primitive_len(GPUPrimType prim_type);
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
|
|
||||||
#define GPU_VERT_ATTR_MAX_LEN 16
|
#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_NAME_AVERAGE_LEN 11
|
||||||
#define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN)
|
#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;
|
uint packed : 1;
|
||||||
/** Current offset in names[]. */
|
/** Current offset in names[]. */
|
||||||
uint name_offset : 8;
|
uint name_offset : 8;
|
||||||
|
/** Store each attrib in one contiguous buffer region. */
|
||||||
|
uint deinterleaved : 1;
|
||||||
|
|
||||||
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
|
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
|
||||||
char names[GPU_VERT_ATTR_NAMES_BUF_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);
|
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
|
||||||
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
|
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);
|
int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name);
|
||||||
|
|
||||||
BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format,
|
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 } */
|
int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */
|
||||||
} GPUPackedNormal;
|
} GPUPackedNormal;
|
||||||
|
|
||||||
GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]);
|
/* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
|
||||||
GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3]);
|
* 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__ */
|
#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. */
|
/* Returns the index of verts in the batch. */
|
||||||
int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
|
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 GPUVertFormat *format = &verts->format;
|
||||||
|
|
||||||
const uint attr_len = format->attr_len;
|
const uint attr_len = format->attr_len;
|
||||||
const uint stride = format->stride;
|
uint stride = format->stride;
|
||||||
|
uint offset = 0;
|
||||||
|
|
||||||
GPU_vertbuf_use(verts);
|
GPU_vertbuf_use(verts);
|
||||||
|
|
||||||
for (uint a_idx = 0; a_idx < attr_len; ++a_idx) {
|
for (uint a_idx = 0; a_idx < attr_len; ++a_idx) {
|
||||||
const GPUVertAttr *a = &format->attrs[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) {
|
for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
|
||||||
const char *name = GPU_vertformat_attr_name_get(format, a, 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)
|
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) {
|
/* Reverse order so first vbos have more prevalence (in term of attrib override). */
|
||||||
create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
|
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) {
|
if (batch->inst) {
|
||||||
create_bindings(batch->inst, batch->interface, v_first, true);
|
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 GPU_TRACK_INDEX_RANGE
|
||||||
if (el->index_type == GPU_INDEX_U16) {
|
if (el->index_type == GPU_INDEX_U16) {
|
||||||
return (GLushort *)0 + v_first;
|
return (GLushort *)0 + v_first + el->index_start;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return (GLuint *)0 + v_first;
|
return (GLuint *)0 + v_first + el->index_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use when drawing with GPU_batch_draw_advanced */
|
/* 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);
|
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
|
#if GPU_TRACK_INDEX_RANGE
|
||||||
/* Everything remains 32 bit while building to keep things simple.
|
/* Everything remains 32 bit while building to keep things simple.
|
||||||
* Find min/max after, then convert to smallest index type possible. */
|
* 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)
|
void GPU_indexbuf_use(GPUIndexBuf *elem)
|
||||||
{
|
{
|
||||||
|
if (elem->is_subrange) {
|
||||||
|
GPU_indexbuf_use(elem->src);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (elem->ibo_id == 0) {
|
if (elem->ibo_id == 0) {
|
||||||
elem->ibo_id = GPU_buf_alloc();
|
elem->ibo_id = GPU_buf_alloc();
|
||||||
}
|
}
|
||||||
@@ -285,7 +383,7 @@ void GPU_indexbuf_discard(GPUIndexBuf *elem)
|
|||||||
if (elem->ibo_id) {
|
if (elem->ibo_id) {
|
||||||
GPU_buf_free(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->data);
|
||||||
}
|
}
|
||||||
MEM_freeN(elem);
|
MEM_freeN(elem);
|
||||||
|
@@ -216,6 +216,29 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
|
|||||||
return -1;
|
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)
|
uint padding(uint offset, uint alignment)
|
||||||
{
|
{
|
||||||
const uint mod = offset % 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__
|
#define __GPU_VERTEX_FORMAT_PRIVATE_H__
|
||||||
|
|
||||||
void VertexFormat_pack(GPUVertFormat *format);
|
void VertexFormat_pack(GPUVertFormat *format);
|
||||||
|
void VertexFormat_deinterleave(GPUVertFormat *format, uint vertex_len);
|
||||||
uint padding(uint offset, uint alignment);
|
uint padding(uint offset, uint alignment);
|
||||||
uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len);
|
uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len);
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ in vec2 pos;
|
|||||||
in float stretch;
|
in float stretch;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
in vec4 uv_adj;
|
in vec2 uv_angles;
|
||||||
in float angle;
|
in float angle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -52,6 +52,11 @@ vec3 weight_to_rgb(float weight)
|
|||||||
|
|
||||||
#define M_PI 3.1415926535897932
|
#define M_PI 3.1415926535897932
|
||||||
|
|
||||||
|
vec2 angle_to_v2(float angle)
|
||||||
|
{
|
||||||
|
return vec2(cos(angle), sin(angle));
|
||||||
|
}
|
||||||
|
|
||||||
/* Adapted from BLI_math_vector.h */
|
/* Adapted from BLI_math_vector.h */
|
||||||
float angle_normalized_v2v2(vec2 v1, vec2 v2)
|
float angle_normalized_v2v2(vec2 v1, vec2 v2)
|
||||||
{
|
{
|
||||||
@@ -69,7 +74,9 @@ void main()
|
|||||||
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
|
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
|
||||||
|
|
||||||
#ifdef STRETCH_ANGLE
|
#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);
|
float stretch = 1.0 - abs(uv_angle - angle);
|
||||||
stretch = stretch;
|
stretch = stretch;
|
||||||
stretch = 1.0 - stretch * stretch;
|
stretch = 1.0 - stretch * stretch;
|
||||||
|
Reference in New Issue
Block a user