The core issue was that the geometry batch cache (e.g. `MeshBatchCache` or `PointCloudBatchCache`) was dependent on the object. This is problematic when the the same geometry is used with multiple different objects because the cache can't be consistent with all of them. Fortunately, the only thing that was retrieved from the object was the number of material slots, so if that can be avoided we should be fine. We can't just use the number of material slots stored on the geometry because that may have no material slots but still has material indices which are overridden on the object level. The solution is to take make the number of materials for a geometry only dependent on the actual `material_index` attribute and not on the number of available slots. More specifically, we find the maximal referenced material index and handle that many materials. This number does not depend on how many material slots there are on the object, but it still allows the object to override materials slots that the mesh references. A downside is that the maximum material index has to be computed which often requires an iteration over the mesh. Fortunately, we can cache that quite easily and the computation can be done in parallel. Also we are probably able to eagerly update the material index in many cases when it's set instead of computing it lazily. That is not implemented in this patch though. The largest part of the patch is making the maximal material index easily available on all the geometry types. Besides that, the material API is slightly replaced and the drawing code now makes use of the updated API. Pull Request: https://projects.blender.org/blender/blender/pulls/133498
3440 lines
107 KiB
C++
3440 lines
107 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup draw
|
|
*/
|
|
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_curves_types.h"
|
|
#include "DNA_grease_pencil_types.h"
|
|
#include "DNA_lattice_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_modifier_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_particle_types.h"
|
|
#include "DNA_pointcloud_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_volume_types.h"
|
|
|
|
#include "UI_resources.hh"
|
|
|
|
#include "BLI_ghash.h"
|
|
#include "BLI_string.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "BKE_context.hh"
|
|
#include "BKE_material.hh"
|
|
#include "BKE_object.hh"
|
|
|
|
#include "GPU_batch.hh"
|
|
#include "GPU_batch_utils.hh"
|
|
#include "GPU_capabilities.hh"
|
|
|
|
#include "draw_cache.hh"
|
|
#include "draw_cache_impl.hh"
|
|
#include "draw_manager_c.hh"
|
|
|
|
using blender::Span;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Internal Defines
|
|
* \{ */
|
|
|
|
#define VCLASS_LIGHT_AREA_SHAPE (1 << 0)
|
|
#define VCLASS_LIGHT_SPOT_SHAPE (1 << 1)
|
|
#define VCLASS_LIGHT_SPOT_BLEND (1 << 2)
|
|
#define VCLASS_LIGHT_SPOT_CONE (1 << 3)
|
|
#define VCLASS_LIGHT_DIST (1 << 4)
|
|
|
|
#define VCLASS_CAMERA_FRAME (1 << 5)
|
|
#define VCLASS_CAMERA_DIST (1 << 6)
|
|
#define VCLASS_CAMERA_VOLUME (1 << 7)
|
|
|
|
#define VCLASS_SCREENSPACE (1 << 8)
|
|
#define VCLASS_SCREENALIGNED (1 << 9)
|
|
|
|
#define VCLASS_EMPTY_SCALED (1 << 10)
|
|
#define VCLASS_EMPTY_AXES (1 << 11)
|
|
#define VCLASS_EMPTY_AXES_NAME (1 << 12)
|
|
#define VCLASS_EMPTY_AXES_SHADOW (1 << 13)
|
|
#define VCLASS_EMPTY_SIZE (1 << 14)
|
|
|
|
/* Sphere shape resolution */
|
|
/* Low */
|
|
#define DRW_SPHERE_SHAPE_LATITUDE_LOW 32
|
|
#define DRW_SPHERE_SHAPE_LONGITUDE_LOW 24
|
|
/* Medium */
|
|
#define DRW_SPHERE_SHAPE_LATITUDE_MEDIUM 64
|
|
#define DRW_SPHERE_SHAPE_LONGITUDE_MEDIUM 48
|
|
/* High */
|
|
#define DRW_SPHERE_SHAPE_LATITUDE_HIGH 80
|
|
#define DRW_SPHERE_SHAPE_LONGITUDE_HIGH 60
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Internal Types
|
|
* \{ */
|
|
|
|
struct Vert {
|
|
float pos[3];
|
|
int v_class;
|
|
|
|
/** Allows creating a pointer to `Vert` in a single expression. */
|
|
operator const void *() const
|
|
{
|
|
return this;
|
|
}
|
|
};
|
|
|
|
struct VertShaded {
|
|
float pos[3];
|
|
int v_class;
|
|
float nor[3];
|
|
|
|
operator const void *() const
|
|
{
|
|
return this;
|
|
}
|
|
};
|
|
|
|
/* Batch's only (freed as an array). */
|
|
static struct DRWShapeCache {
|
|
blender::gpu::Batch *drw_procedural_verts;
|
|
blender::gpu::Batch *drw_procedural_lines;
|
|
blender::gpu::Batch *drw_procedural_tris;
|
|
blender::gpu::Batch *drw_procedural_tri_strips;
|
|
blender::gpu::Batch *drw_cursor;
|
|
blender::gpu::Batch *drw_cursor_only_circle;
|
|
blender::gpu::Batch *drw_fullscreen_quad;
|
|
blender::gpu::Batch *drw_quad;
|
|
blender::gpu::Batch *drw_quad_wires;
|
|
blender::gpu::Batch *drw_grid;
|
|
blender::gpu::Batch *drw_plain_axes;
|
|
blender::gpu::Batch *drw_single_arrow;
|
|
blender::gpu::Batch *drw_cube;
|
|
blender::gpu::Batch *drw_circle;
|
|
blender::gpu::Batch *drw_normal_arrow;
|
|
blender::gpu::Batch *drw_empty_cube;
|
|
blender::gpu::Batch *drw_empty_sphere;
|
|
blender::gpu::Batch *drw_empty_cylinder;
|
|
blender::gpu::Batch *drw_empty_capsule_body;
|
|
blender::gpu::Batch *drw_empty_capsule_cap;
|
|
blender::gpu::Batch *drw_empty_cone;
|
|
blender::gpu::Batch *drw_field_wind;
|
|
blender::gpu::Batch *drw_field_force;
|
|
blender::gpu::Batch *drw_field_vortex;
|
|
blender::gpu::Batch *drw_field_curve;
|
|
blender::gpu::Batch *drw_field_tube_limit;
|
|
blender::gpu::Batch *drw_field_cone_limit;
|
|
blender::gpu::Batch *drw_field_sphere_limit;
|
|
blender::gpu::Batch *drw_ground_line;
|
|
blender::gpu::Batch *drw_light_icon_inner_lines;
|
|
blender::gpu::Batch *drw_light_icon_outer_lines;
|
|
blender::gpu::Batch *drw_light_icon_sun_rays;
|
|
blender::gpu::Batch *drw_light_point_lines;
|
|
blender::gpu::Batch *drw_light_sun_lines;
|
|
blender::gpu::Batch *drw_light_spot_lines;
|
|
blender::gpu::Batch *drw_light_spot_volume;
|
|
blender::gpu::Batch *drw_light_area_disk_lines;
|
|
blender::gpu::Batch *drw_light_area_square_lines;
|
|
blender::gpu::Batch *drw_speaker;
|
|
blender::gpu::Batch *drw_lightprobe_cube;
|
|
blender::gpu::Batch *drw_lightprobe_planar;
|
|
blender::gpu::Batch *drw_lightprobe_grid;
|
|
blender::gpu::Batch *drw_bone_octahedral;
|
|
blender::gpu::Batch *drw_bone_octahedral_wire;
|
|
blender::gpu::Batch *drw_bone_box;
|
|
blender::gpu::Batch *drw_bone_box_wire;
|
|
blender::gpu::Batch *drw_bone_envelope;
|
|
blender::gpu::Batch *drw_bone_envelope_outline;
|
|
blender::gpu::Batch *drw_bone_point;
|
|
blender::gpu::Batch *drw_bone_point_wire;
|
|
blender::gpu::Batch *drw_bone_stick;
|
|
blender::gpu::Batch *drw_bone_arrows;
|
|
blender::gpu::Batch *drw_bone_dof_sphere;
|
|
blender::gpu::Batch *drw_bone_dof_lines;
|
|
blender::gpu::Batch *drw_camera_frame;
|
|
blender::gpu::Batch *drw_camera_tria;
|
|
blender::gpu::Batch *drw_camera_tria_wire;
|
|
blender::gpu::Batch *drw_camera_distances;
|
|
blender::gpu::Batch *drw_camera_volume;
|
|
blender::gpu::Batch *drw_camera_volume_wire;
|
|
blender::gpu::Batch *drw_particle_cross;
|
|
blender::gpu::Batch *drw_particle_circle;
|
|
blender::gpu::Batch *drw_particle_axis;
|
|
blender::gpu::Batch *drw_gpencil_dummy_quad;
|
|
blender::gpu::Batch *drw_sphere_lod[DRW_LOD_MAX];
|
|
} SHC = {nullptr};
|
|
|
|
void DRW_shape_cache_free()
|
|
{
|
|
uint i = sizeof(SHC) / sizeof(blender::gpu::Batch *);
|
|
blender::gpu::Batch **batch = (blender::gpu::Batch **)&SHC;
|
|
while (i--) {
|
|
GPU_BATCH_DISCARD_SAFE(*batch);
|
|
batch++;
|
|
}
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Procedural Batches
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *drw_cache_procedural_points_get()
|
|
{
|
|
if (!SHC.drw_procedural_verts) {
|
|
/* TODO(fclem): get rid of this dummy VBO. */
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 1);
|
|
|
|
SHC.drw_procedural_verts = GPU_batch_create_ex(
|
|
GPU_PRIM_POINTS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_procedural_verts;
|
|
}
|
|
|
|
blender::gpu::Batch *drw_cache_procedural_lines_get()
|
|
{
|
|
if (!SHC.drw_procedural_lines) {
|
|
/* TODO(fclem): get rid of this dummy VBO. */
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 1);
|
|
|
|
SHC.drw_procedural_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_procedural_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *drw_cache_procedural_triangles_get()
|
|
{
|
|
if (!SHC.drw_procedural_tris) {
|
|
/* TODO(fclem): get rid of this dummy VBO. */
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 1);
|
|
|
|
SHC.drw_procedural_tris = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_procedural_tris;
|
|
}
|
|
|
|
blender::gpu::Batch *drw_cache_procedural_triangle_strips_get()
|
|
{
|
|
if (!SHC.drw_procedural_tri_strips) {
|
|
/* TODO(fclem): get rid of this dummy VBO. */
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 1);
|
|
|
|
SHC.drw_procedural_tri_strips = GPU_batch_create_ex(
|
|
GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_procedural_tri_strips;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Helper functions
|
|
* \{ */
|
|
|
|
static GPUVertFormat extra_vert_format()
|
|
{
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
GPU_vertformat_attr_add(&format, "vclass", GPU_COMP_I32, 1, GPU_FETCH_INT);
|
|
return format;
|
|
}
|
|
|
|
static void UNUSED_FUNCTION(add_fancy_edge)(blender::gpu::VertBuf *vbo,
|
|
uint pos_id,
|
|
uint n1_id,
|
|
uint n2_id,
|
|
uint *v_idx,
|
|
const float co1[3],
|
|
const float co2[3],
|
|
const float n1[3],
|
|
const float n2[3])
|
|
{
|
|
GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
|
|
GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1);
|
|
|
|
GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
|
|
GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2);
|
|
}
|
|
|
|
#if 0 /* UNUSED */
|
|
static void add_lat_lon_vert(blender::gpu::VertBuf *vbo,
|
|
uint pos_id,
|
|
uint nor_id,
|
|
uint *v_idx,
|
|
const float rad,
|
|
const float lat,
|
|
const float lon)
|
|
{
|
|
float pos[3], nor[3];
|
|
nor[0] = sinf(lat) * cosf(lon);
|
|
nor[1] = cosf(lat);
|
|
nor[2] = sinf(lat) * sinf(lon);
|
|
mul_v3_v3fl(pos, nor, rad);
|
|
|
|
GPU_vertbuf_attr_set(vbo, nor_id, *v_idx, nor);
|
|
GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos);
|
|
}
|
|
|
|
static blender::gpu::VertBuf *fill_arrows_vbo(const float scale)
|
|
{
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
/* Line */
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 6 * 3);
|
|
|
|
float v1[3] = {0.0, 0.0, 0.0};
|
|
float v2[3] = {0.0, 0.0, 0.0};
|
|
float vtmp1[3], vtmp2[3];
|
|
|
|
for (int axis = 0; axis < 3; axis++) {
|
|
const int arrow_axis = (axis == 0) ? 1 : 0;
|
|
|
|
v2[axis] = 1.0f;
|
|
mul_v3_v3fl(vtmp1, v1, scale);
|
|
mul_v3_v3fl(vtmp2, v2, scale);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 1, vtmp2);
|
|
|
|
v1[axis] = 0.85f;
|
|
v1[arrow_axis] = -0.08f;
|
|
mul_v3_v3fl(vtmp1, v1, scale);
|
|
mul_v3_v3fl(vtmp2, v2, scale);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2);
|
|
|
|
v1[arrow_axis] = 0.08f;
|
|
mul_v3_v3fl(vtmp1, v1, scale);
|
|
mul_v3_v3fl(vtmp2, v2, scale);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2);
|
|
|
|
/* reset v1 & v2 to zero */
|
|
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
|
|
}
|
|
|
|
return vbo;
|
|
}
|
|
#endif /* UNUSED */
|
|
|
|
static blender::gpu::VertBuf *sphere_wire_vbo(const float rad, int flag)
|
|
{
|
|
#define NSEGMENTS 32
|
|
/* Position Only 3D format */
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, NSEGMENTS * 2 * 3);
|
|
|
|
int v = 0;
|
|
/* a single ring of vertices */
|
|
float p[NSEGMENTS][2];
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float angle = 2 * M_PI * (float(i) / float(NSEGMENTS));
|
|
p[i][0] = rad * cosf(angle);
|
|
p[i][1] = rad * sinf(angle);
|
|
}
|
|
|
|
for (int axis = 0; axis < 3; axis++) {
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
for (int j = 0; j < 2; j++) {
|
|
float cv[2];
|
|
|
|
cv[0] = p[(i + j) % NSEGMENTS][0];
|
|
cv[1] = p[(i + j) % NSEGMENTS][1];
|
|
|
|
if (axis == 0) {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], cv[1], 0.0f}, flag});
|
|
}
|
|
else if (axis == 1) {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], 0.0f, cv[1]}, flag});
|
|
}
|
|
else {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, cv[0], cv[1]}, flag});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return vbo;
|
|
#undef NSEGMENTS
|
|
}
|
|
|
|
/* Quads */
|
|
|
|
blender::gpu::Batch *DRW_cache_fullscreen_quad_get()
|
|
{
|
|
if (!SHC.drw_fullscreen_quad) {
|
|
/* Use a triangle instead of a real quad */
|
|
/* https://www.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau - slide 14 */
|
|
const float pos[3][2] = {{-1.0f, -1.0f}, {3.0f, -1.0f}, {-1.0f, 3.0f}};
|
|
const float uvs[3][2] = {{0.0f, 0.0f}, {2.0f, 0.0f}, {0.0f, 2.0f}};
|
|
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, uvs;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
GPU_vertformat_alias_add(&format, "texCoord");
|
|
GPU_vertformat_alias_add(&format, "orco"); /* Fix driver bug (see #70004) */
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 3);
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
|
|
}
|
|
|
|
SHC.drw_fullscreen_quad = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_fullscreen_quad;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_quad_get()
|
|
{
|
|
if (!SHC.drw_quad) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 4);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
const float p[4][2] = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, {1.0f, -1.0f}};
|
|
for (int a = 0; a < 4; a++) {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[a][0], p[a][1], 0.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_quad;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_quad_wires_get()
|
|
{
|
|
if (!SHC.drw_quad_wires) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 5);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
const float p[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
|
|
for (int a = 0; a < 5; a++) {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[a % 4][0], p[a % 4][1], 0.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_quad_wires = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_quad_wires;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_grid_get()
|
|
{
|
|
if (!SHC.drw_grid) {
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 8 * 8 * 2 * 3);
|
|
|
|
uint v_idx = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
for (int j = 0; j < 8; j++) {
|
|
float pos0[2] = {float(i) / 8.0f, float(j) / 8.0f};
|
|
float pos1[2] = {float(i + 1) / 8.0f, float(j) / 8.0f};
|
|
float pos2[2] = {float(i) / 8.0f, float(j + 1) / 8.0f};
|
|
float pos3[2] = {float(i + 1) / 8.0f, float(j + 1) / 8.0f};
|
|
|
|
madd_v2_v2v2fl(pos0, blender::float2{-1.0f, -1.0f}, pos0, 2.0f);
|
|
madd_v2_v2v2fl(pos1, blender::float2{-1.0f, -1.0f}, pos1, 2.0f);
|
|
madd_v2_v2v2fl(pos2, blender::float2{-1.0f, -1.0f}, pos2, 2.0f);
|
|
madd_v2_v2v2fl(pos3, blender::float2{-1.0f, -1.0f}, pos3, 2.0f);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos0);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos2);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos2);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos3);
|
|
}
|
|
}
|
|
|
|
SHC.drw_grid = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_grid;
|
|
}
|
|
|
|
/* Sphere */
|
|
static void sphere_lat_lon_vert(blender::gpu::VertBuf *vbo, int *v_ofs, float lat, float lon)
|
|
{
|
|
float x = sinf(lat) * cosf(lon);
|
|
float y = cosf(lat);
|
|
float z = sinf(lat) * sinf(lon);
|
|
GPU_vertbuf_vert_set(vbo, *v_ofs, VertShaded{{x, y, z}, VCLASS_EMPTY_SCALED, {x, y, z}});
|
|
(*v_ofs)++;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_sphere_get(const eDRWLevelOfDetail level_of_detail)
|
|
{
|
|
BLI_assert(level_of_detail >= DRW_LOD_LOW && level_of_detail < DRW_LOD_MAX);
|
|
|
|
if (!SHC.drw_sphere_lod[level_of_detail]) {
|
|
int lat_res;
|
|
int lon_res;
|
|
|
|
switch (level_of_detail) {
|
|
case DRW_LOD_LOW:
|
|
lat_res = DRW_SPHERE_SHAPE_LATITUDE_LOW;
|
|
lon_res = DRW_SPHERE_SHAPE_LONGITUDE_LOW;
|
|
break;
|
|
case DRW_LOD_MEDIUM:
|
|
lat_res = DRW_SPHERE_SHAPE_LATITUDE_MEDIUM;
|
|
lon_res = DRW_SPHERE_SHAPE_LONGITUDE_MEDIUM;
|
|
break;
|
|
case DRW_LOD_HIGH:
|
|
lat_res = DRW_SPHERE_SHAPE_LATITUDE_HIGH;
|
|
lon_res = DRW_SPHERE_SHAPE_LONGITUDE_HIGH;
|
|
break;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
|
|
GPUVertFormat format = extra_vert_format();
|
|
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
int v_len = (lat_res - 1) * lon_res * 6;
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float lon_inc = 2 * M_PI / lon_res;
|
|
const float lat_inc = M_PI / lat_res;
|
|
float lon, lat;
|
|
|
|
int v = 0;
|
|
lon = 0.0f;
|
|
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
|
|
lat = 0.0f;
|
|
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
|
|
if (j != lat_res - 1) { /* Pole */
|
|
sphere_lat_lon_vert(vbo, &v, lat + lat_inc, lon + lon_inc);
|
|
sphere_lat_lon_vert(vbo, &v, lat + lat_inc, lon);
|
|
sphere_lat_lon_vert(vbo, &v, lat, lon);
|
|
}
|
|
if (j != 0) { /* Pole */
|
|
sphere_lat_lon_vert(vbo, &v, lat, lon + lon_inc);
|
|
sphere_lat_lon_vert(vbo, &v, lat + lat_inc, lon + lon_inc);
|
|
sphere_lat_lon_vert(vbo, &v, lat, lon);
|
|
}
|
|
}
|
|
}
|
|
|
|
SHC.drw_sphere_lod[level_of_detail] = GPU_batch_create_ex(
|
|
GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_sphere_lod[level_of_detail];
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Common
|
|
* \{ */
|
|
|
|
static void circle_verts(
|
|
blender::gpu::VertBuf *vbo, int *vert_idx, int segments, float radius, float z, int flag)
|
|
{
|
|
for (int a = 0; a < segments; a++) {
|
|
for (int b = 0; b < 2; b++) {
|
|
float angle = (2.0f * M_PI * (a + b)) / segments;
|
|
float s = sinf(angle) * radius;
|
|
float c = cosf(angle) * radius;
|
|
int v = *vert_idx;
|
|
*vert_idx = v + 1;
|
|
GPU_vertbuf_vert_set(vbo, v, Vert{{s, c, z}, flag});
|
|
}
|
|
}
|
|
}
|
|
|
|
static void circle_dashed_verts(
|
|
blender::gpu::VertBuf *vbo, int *vert_idx, int segments, float radius, float z, int flag)
|
|
{
|
|
for (int a = 0; a < segments * 2; a += 2) {
|
|
for (int b = 0; b < 2; b++) {
|
|
float angle = (2.0f * M_PI * (a + b)) / (segments * 2);
|
|
float s = sinf(angle) * radius;
|
|
float c = cosf(angle) * radius;
|
|
int v = *vert_idx;
|
|
*vert_idx = v + 1;
|
|
GPU_vertbuf_vert_set(vbo, v, Vert{{s, c, z}, flag});
|
|
}
|
|
}
|
|
}
|
|
|
|
/* XXX TODO: move that 1 unit cube to more common/generic place? */
|
|
static const float bone_box_verts[8][3] = {
|
|
{1.0f, 0.0f, 1.0f},
|
|
{1.0f, 0.0f, -1.0f},
|
|
{-1.0f, 0.0f, -1.0f},
|
|
{-1.0f, 0.0f, 1.0f},
|
|
{1.0f, 1.0f, 1.0f},
|
|
{1.0f, 1.0f, -1.0f},
|
|
{-1.0f, 1.0f, -1.0f},
|
|
{-1.0f, 1.0f, 1.0f},
|
|
};
|
|
|
|
static const uint bone_box_wire[24] = {
|
|
0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7,
|
|
};
|
|
|
|
#if 0 /* UNUSED */
|
|
/* aligned with bone_octahedral_wire
|
|
* Contains adjacent normal index */
|
|
static const uint bone_box_wire_adjacent_face[24] = {
|
|
0, 2, 0, 4, 1, 6, 1, 8, 3, 10, 5, 10, 7, 11, 9, 11, 3, 8, 2, 5, 4, 7, 6, 9,
|
|
};
|
|
#endif
|
|
|
|
static const uint bone_box_solid_tris[12][3] = {
|
|
{0, 2, 1}, /* bottom */
|
|
{0, 3, 2},
|
|
|
|
{0, 1, 5}, /* sides */
|
|
{0, 5, 4},
|
|
|
|
{1, 2, 6},
|
|
{1, 6, 5},
|
|
|
|
{2, 3, 7},
|
|
{2, 7, 6},
|
|
|
|
{3, 0, 4},
|
|
{3, 4, 7},
|
|
|
|
{4, 5, 6}, /* top */
|
|
{4, 6, 7},
|
|
};
|
|
|
|
/**
|
|
* Store indices of generated verts from bone_box_solid_tris to define adjacency infos.
|
|
* See bone_octahedral_solid_tris for more infos.
|
|
*/
|
|
static const uint bone_box_wire_lines_adjacency[12][4] = {
|
|
{4, 2, 0, 11},
|
|
{0, 1, 2, 8},
|
|
{2, 4, 1, 14},
|
|
{1, 0, 4, 20}, /* bottom */
|
|
{0, 8, 11, 14},
|
|
{2, 14, 8, 20},
|
|
{1, 20, 14, 11},
|
|
{4, 11, 20, 8}, /* top */
|
|
{20, 0, 11, 2},
|
|
{11, 2, 8, 1},
|
|
{8, 1, 14, 4},
|
|
{14, 4, 20, 0}, /* sides */
|
|
};
|
|
|
|
#if 0 /* UNUSED */
|
|
static const uint bone_box_solid_tris_adjacency[12][6] = {
|
|
{0, 5, 1, 14, 2, 8},
|
|
{3, 26, 4, 20, 5, 1},
|
|
|
|
{6, 2, 7, 16, 8, 11},
|
|
{9, 7, 10, 32, 11, 24},
|
|
|
|
{12, 0, 13, 22, 14, 17},
|
|
{15, 13, 16, 30, 17, 6},
|
|
|
|
{18, 3, 19, 28, 20, 23},
|
|
{21, 19, 22, 33, 23, 12},
|
|
|
|
{24, 4, 25, 10, 26, 29},
|
|
{27, 25, 28, 34, 29, 18},
|
|
|
|
{30, 9, 31, 15, 32, 35},
|
|
{33, 31, 34, 21, 35, 27},
|
|
};
|
|
#endif
|
|
|
|
/* aligned with bone_box_solid_tris */
|
|
static const float bone_box_solid_normals[12][3] = {
|
|
{0.0f, -1.0f, 0.0f},
|
|
{0.0f, -1.0f, 0.0f},
|
|
|
|
{1.0f, 0.0f, 0.0f},
|
|
{1.0f, 0.0f, 0.0f},
|
|
|
|
{0.0f, 0.0f, -1.0f},
|
|
{0.0f, 0.0f, -1.0f},
|
|
|
|
{-1.0f, 0.0f, 0.0f},
|
|
{-1.0f, 0.0f, 0.0f},
|
|
|
|
{0.0f, 0.0f, 1.0f},
|
|
{0.0f, 0.0f, 1.0f},
|
|
|
|
{0.0f, 1.0f, 0.0f},
|
|
{0.0f, 1.0f, 0.0f},
|
|
};
|
|
|
|
blender::gpu::Batch *DRW_cache_cube_get()
|
|
{
|
|
if (!SHC.drw_cube) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int tri_len = ARRAY_SIZE(bone_box_solid_tris);
|
|
const int vert_len = ARRAY_SIZE(bone_box_verts);
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, vert_len);
|
|
|
|
GPUIndexBufBuilder elb;
|
|
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
|
|
|
|
int v = 0;
|
|
for (int i = 0; i < vert_len; i++) {
|
|
float x = bone_box_verts[i][0];
|
|
float y = bone_box_verts[i][1] * 2.0f - 1.0f;
|
|
float z = bone_box_verts[i][2];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, z}, VCLASS_EMPTY_SCALED});
|
|
}
|
|
|
|
for (int i = 0; i < tri_len; i++) {
|
|
const uint *tri_indices = bone_box_solid_tris[i];
|
|
GPU_indexbuf_add_tri_verts(&elb, tri_indices[0], tri_indices[1], tri_indices[2]);
|
|
}
|
|
|
|
SHC.drw_cube = GPU_batch_create_ex(
|
|
GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
|
}
|
|
return SHC.drw_cube;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_circle_get()
|
|
{
|
|
#define CIRCLE_RESOL 64
|
|
if (!SHC.drw_circle) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, CIRCLE_RESOL + 1);
|
|
|
|
int v = 0;
|
|
for (int a = 0; a < CIRCLE_RESOL + 1; a++) {
|
|
float x = sinf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
float z = cosf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
float y = 0.0f;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, z}, VCLASS_EMPTY_SCALED});
|
|
}
|
|
|
|
SHC.drw_circle = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_circle;
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_normal_arrow_get()
|
|
{
|
|
if (!SHC.drw_normal_arrow) {
|
|
GPUVertFormat format = {0};
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 2);
|
|
|
|
/* TODO: real arrow. For now, it's a line positioned in the vertex shader. */
|
|
|
|
SHC.drw_normal_arrow = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_normal_arrow;
|
|
}
|
|
|
|
namespace blender::draw {
|
|
|
|
void DRW_vertbuf_create_wiredata(blender::gpu::VertBuf *vbo, const int vert_len)
|
|
{
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint wd;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
/* initialize vertex format */
|
|
if (!GPU_crappy_amd_driver()) {
|
|
/* Some AMD drivers strangely crash with a vbo with this format. */
|
|
attr_id.wd = GPU_vertformat_attr_add(
|
|
&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
|
}
|
|
else {
|
|
attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
}
|
|
}
|
|
|
|
GPU_vertbuf_init_with_format(*vbo, format);
|
|
GPU_vertbuf_data_alloc(*vbo, vert_len);
|
|
|
|
if (GPU_vertbuf_get_format(vbo)->stride == 1) {
|
|
memset(vbo->data<uint8_t>().data(), 0xFF, size_t(vert_len));
|
|
}
|
|
else {
|
|
GPUVertBufRaw wd_step;
|
|
GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
|
|
for (int i = 0; i < vert_len; i++) {
|
|
*((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Dummy VBO's
|
|
*
|
|
* We need a dummy VBO containing the vertex count to draw instances ranges.
|
|
*
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_gpencil_dummy_buffer_get()
|
|
{
|
|
if (SHC.drw_gpencil_dummy_quad == nullptr) {
|
|
GPUVertFormat format = {0};
|
|
/* NOTE: Use GPU_COMP_U32 to satisfy minimum 4-byte vertex stride for Metal backend. */
|
|
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 4);
|
|
|
|
SHC.drw_gpencil_dummy_quad = GPU_batch_create_ex(
|
|
GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_gpencil_dummy_quad;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Common Object API
|
|
*
|
|
* \note Curve and text objects evaluate to the evaluated geometry set's mesh component if
|
|
* they have a surface, so curve objects themselves do not have a surface (the mesh component
|
|
* is presented to render engines as a separate object).
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_object_all_edges_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_all_edges_get(ob);
|
|
/* TODO: should match #DRW_cache_object_surface_get. */
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_face_wireframe_get(const Scene *scene, Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_face_wireframe_get(ob);
|
|
case OB_POINTCLOUD:
|
|
return DRW_pointcloud_batch_cache_get_dots(ob);
|
|
case OB_VOLUME:
|
|
return DRW_cache_volume_face_wireframe_get(ob);
|
|
case OB_GREASE_PENCIL:
|
|
return DRW_cache_grease_pencil_face_wireframe_get(scene, ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_loose_edges_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_loose_edges_get(ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_surface_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_surface_get(ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::VertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(ob);
|
|
short type = (mesh != nullptr) ? short(OB_MESH) : ob->type;
|
|
|
|
switch (type) {
|
|
case OB_MESH:
|
|
return DRW_mesh_batch_cache_pos_vertbuf_get(
|
|
*static_cast<Mesh *>((mesh != nullptr) ? mesh : ob->data));
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_object_surface_material_get(
|
|
Object *ob, const Span<const GPUMaterial *> materials)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_surface_shaded_get(ob, materials);
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Empties
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_plain_axes_get()
|
|
{
|
|
if (!SHC.drw_plain_axes) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 6);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, -1.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 1.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{-1.0f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{1.0f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, -1.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 1.0f}, flag});
|
|
|
|
SHC.drw_plain_axes = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_plain_axes;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_cube_get()
|
|
{
|
|
if (!SHC.drw_empty_cube) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, ARRAY_SIZE(bone_box_wire));
|
|
|
|
int v = 0;
|
|
for (int i = 0; i < ARRAY_SIZE(bone_box_wire); i++) {
|
|
float x = bone_box_verts[bone_box_wire[i]][0];
|
|
float y = bone_box_verts[bone_box_wire[i]][1] * 2.0 - 1.0f;
|
|
float z = bone_box_verts[bone_box_wire[i]][2];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, z}, VCLASS_EMPTY_SCALED});
|
|
}
|
|
|
|
SHC.drw_empty_cube = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_cube;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_single_arrow_get()
|
|
{
|
|
if (!SHC.drw_single_arrow) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 4 * 2 * 2 + 2);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
float p[3][3] = {{0}};
|
|
p[0][2] = 1.0f;
|
|
p[1][0] = 0.035f;
|
|
p[1][1] = 0.035f;
|
|
p[2][0] = -0.035f;
|
|
p[2][1] = 0.035f;
|
|
p[1][2] = p[2][2] = 0.75f;
|
|
for (int sides = 0; sides < 4; sides++) {
|
|
if (sides % 2 == 1) {
|
|
p[1][0] = -p[1][0];
|
|
p[2][1] = -p[2][1];
|
|
}
|
|
else {
|
|
p[1][1] = -p[1][1];
|
|
p[2][0] = -p[2][0];
|
|
}
|
|
for (int i = 0, a = 1; i < 2; i++, a++) {
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[i][0], p[i][1], p[i][2]}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[a][0], p[a][1], p[a][2]}, flag});
|
|
}
|
|
}
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.0}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.75f}, flag});
|
|
|
|
SHC.drw_single_arrow = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_single_arrow;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_sphere_get()
|
|
{
|
|
if (!SHC.drw_empty_sphere) {
|
|
blender::gpu::VertBuf *vbo = sphere_wire_vbo(1.0f, VCLASS_EMPTY_SCALED);
|
|
SHC.drw_empty_sphere = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_sphere;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_cone_get()
|
|
{
|
|
#define NSEGMENTS 8
|
|
if (!SHC.drw_empty_cone) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, NSEGMENTS * 4);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
/* a single ring of vertices */
|
|
float p[NSEGMENTS][2];
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float angle = 2 * M_PI * (float(i) / float(NSEGMENTS));
|
|
p[i][0] = cosf(angle);
|
|
p[i][1] = sinf(angle);
|
|
}
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float cv[2];
|
|
cv[0] = p[(i) % NSEGMENTS][0];
|
|
cv[1] = p[(i) % NSEGMENTS][1];
|
|
|
|
/* cone sides */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], 0.0f, cv[1]}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 2.0f, 0.0f}, flag});
|
|
|
|
/* end ring */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], 0.0f, cv[1]}, flag});
|
|
cv[0] = p[(i + 1) % NSEGMENTS][0];
|
|
cv[1] = p[(i + 1) % NSEGMENTS][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], 0.0f, cv[1]}, flag});
|
|
}
|
|
|
|
SHC.drw_empty_cone = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_cone;
|
|
#undef NSEGMENTS
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_cylinder_get()
|
|
{
|
|
#define NSEGMENTS 12
|
|
if (!SHC.drw_empty_cylinder) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, NSEGMENTS * 6);
|
|
|
|
/* a single ring of vertices */
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SCALED;
|
|
float p[NSEGMENTS][2];
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float angle = 2 * M_PI * (float(i) / float(NSEGMENTS));
|
|
p[i][0] = cosf(angle);
|
|
p[i][1] = sinf(angle);
|
|
}
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float cv[2], pv[2];
|
|
cv[0] = p[(i) % NSEGMENTS][0];
|
|
cv[1] = p[(i) % NSEGMENTS][1];
|
|
pv[0] = p[(i + 1) % NSEGMENTS][0];
|
|
pv[1] = p[(i + 1) % NSEGMENTS][1];
|
|
|
|
/* cylinder sides */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], cv[1], -1.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], cv[1], 1.0f}, flag});
|
|
/* top ring */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], cv[1], 1.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{pv[0], pv[1], 1.0f}, flag});
|
|
/* bottom ring */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{cv[0], cv[1], -1.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{pv[0], pv[1], -1.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_empty_cylinder = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_cylinder;
|
|
#undef NSEGMENTS
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_capsule_body_get()
|
|
{
|
|
if (!SHC.drw_empty_capsule_body) {
|
|
const float pos[8][3] = {
|
|
{1.0f, 0.0f, 1.0f},
|
|
{1.0f, 0.0f, 0.0f},
|
|
{0.0f, 1.0f, 1.0f},
|
|
{0.0f, 1.0f, 0.0f},
|
|
{-1.0f, 0.0f, 1.0f},
|
|
{-1.0f, 0.0f, 0.0f},
|
|
{0.0f, -1.0f, 1.0f},
|
|
{0.0f, -1.0f, 0.0f},
|
|
};
|
|
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 8);
|
|
GPU_vertbuf_attr_fill(vbo, attr_id.pos, pos);
|
|
|
|
SHC.drw_empty_capsule_body = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_capsule_body;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_empty_capsule_cap_get()
|
|
{
|
|
#define NSEGMENTS 24 /* Must be multiple of 2. */
|
|
if (!SHC.drw_empty_capsule_cap) {
|
|
/* a single ring of vertices */
|
|
float p[NSEGMENTS][2];
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float angle = 2 * M_PI * (float(i) / float(NSEGMENTS));
|
|
p[i][0] = cosf(angle);
|
|
p[i][1] = sinf(angle);
|
|
}
|
|
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, (NSEGMENTS * 2) * 2);
|
|
|
|
/* Base circle */
|
|
int vidx = 0;
|
|
for (int i = 0; i < NSEGMENTS; i++) {
|
|
float v[3] = {0.0f, 0.0f, 0.0f};
|
|
copy_v2_v2(v, p[(i) % NSEGMENTS]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
copy_v2_v2(v, p[(i + 1) % NSEGMENTS]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
}
|
|
|
|
for (int i = 0; i < NSEGMENTS / 2; i++) {
|
|
float v[3] = {0.0f, 0.0f, 0.0f};
|
|
int ci = i % NSEGMENTS;
|
|
int pi = (i + 1) % NSEGMENTS;
|
|
/* Y half circle */
|
|
copy_v3_fl3(v, p[ci][0], 0.0f, p[ci][1]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
copy_v3_fl3(v, p[pi][0], 0.0f, p[pi][1]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
/* X half circle */
|
|
copy_v3_fl3(v, 0.0f, p[ci][0], p[ci][1]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
copy_v3_fl3(v, 0.0f, p[pi][0], p[pi][1]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
}
|
|
|
|
SHC.drw_empty_capsule_cap = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_empty_capsule_cap;
|
|
#undef NSEGMENTS
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_wind_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
if (!SHC.drw_field_wind) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (CIRCLE_RESOL * 4);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE;
|
|
for (int i = 0; i < 4; i++) {
|
|
float z = 0.05f * float(i);
|
|
circle_verts(vbo, &v, CIRCLE_RESOL, 1.0f, z, flag);
|
|
}
|
|
|
|
SHC.drw_field_wind = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_wind;
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_force_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
if (!SHC.drw_field_force) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (CIRCLE_RESOL * 3);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE | VCLASS_SCREENALIGNED;
|
|
for (int i = 0; i < 3; i++) {
|
|
float radius = 1.0f + 0.5f * i;
|
|
circle_verts(vbo, &v, CIRCLE_RESOL, radius, 0.0f, flag);
|
|
}
|
|
|
|
SHC.drw_field_force = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_force;
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_vortex_get()
|
|
{
|
|
#define SPIRAL_RESOL 32
|
|
if (!SHC.drw_field_vortex) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = SPIRAL_RESOL * 2 + 1;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE;
|
|
for (int a = SPIRAL_RESOL; a > -1; a--) {
|
|
float r = a / float(SPIRAL_RESOL);
|
|
float angle = (2.0f * M_PI * a) / SPIRAL_RESOL;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{sinf(angle) * r, cosf(angle) * r, 0.0f}, flag});
|
|
}
|
|
for (int a = 1; a <= SPIRAL_RESOL; a++) {
|
|
float r = a / float(SPIRAL_RESOL);
|
|
float angle = (2.0f * M_PI * a) / SPIRAL_RESOL;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{sinf(angle) * -r, cosf(angle) * -r, 0.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_field_vortex = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_vortex;
|
|
#undef SPIRAL_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_curve_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
if (!SHC.drw_field_curve) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (CIRCLE_RESOL);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE | VCLASS_SCREENALIGNED;
|
|
circle_verts(vbo, &v, CIRCLE_RESOL, 1.0f, 0.0f, flag);
|
|
|
|
SHC.drw_field_curve = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_curve;
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_tube_limit_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
#define SIDE_STIPPLE 32
|
|
if (!SHC.drw_field_tube_limit) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (CIRCLE_RESOL * 2 + 4 * SIDE_STIPPLE / 2);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE;
|
|
/* Caps */
|
|
for (int i = 0; i < 2; i++) {
|
|
float z = i * 2.0f - 1.0f;
|
|
circle_dashed_verts(vbo, &v, CIRCLE_RESOL, 1.0f, z, flag);
|
|
}
|
|
/* Side Edges */
|
|
for (int a = 0; a < 4; a++) {
|
|
float angle = (2.0f * M_PI * a) / 4.0f;
|
|
for (int i = 0; i < SIDE_STIPPLE; i++) {
|
|
float z = (i / float(SIDE_STIPPLE)) * 2.0f - 1.0f;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{sinf(angle), cosf(angle), z}, flag});
|
|
}
|
|
}
|
|
|
|
SHC.drw_field_tube_limit = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_tube_limit;
|
|
#undef SIDE_STIPPLE
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_cone_limit_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
#define SIDE_STIPPLE 32
|
|
if (!SHC.drw_field_cone_limit) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (CIRCLE_RESOL * 2 + 4 * SIDE_STIPPLE / 2);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE;
|
|
/* Caps */
|
|
for (int i = 0; i < 2; i++) {
|
|
float z = i * 2.0f - 1.0f;
|
|
circle_dashed_verts(vbo, &v, CIRCLE_RESOL, 1.0f, z, flag);
|
|
}
|
|
/* Side Edges */
|
|
for (int a = 0; a < 4; a++) {
|
|
float angle = (2.0f * M_PI * a) / 4.0f;
|
|
for (int i = 0; i < SIDE_STIPPLE; i++) {
|
|
float z = (i / float(SIDE_STIPPLE)) * 2.0f - 1.0f;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{sinf(angle) * z, cosf(angle) * z, z}, flag});
|
|
}
|
|
}
|
|
|
|
SHC.drw_field_cone_limit = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_cone_limit;
|
|
#undef SIDE_STIPPLE
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_field_sphere_limit_get()
|
|
{
|
|
#define CIRCLE_RESOL 32
|
|
if (!SHC.drw_field_sphere_limit) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * CIRCLE_RESOL;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_SIZE | VCLASS_SCREENALIGNED;
|
|
circle_dashed_verts(vbo, &v, CIRCLE_RESOL, 1.0f, 0.0f, flag);
|
|
|
|
SHC.drw_field_sphere_limit = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_field_sphere_limit;
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Lights
|
|
* \{ */
|
|
|
|
#define DIAMOND_NSEGMENTS 4
|
|
#define INNER_NSEGMENTS 8
|
|
#define OUTER_NSEGMENTS 10
|
|
#define CIRCLE_NSEGMENTS 32
|
|
|
|
static float light_distance_z_get(char axis, const bool start)
|
|
{
|
|
switch (axis) {
|
|
case 'x': /* - X */
|
|
return start ? 0.4f : 0.3f;
|
|
case 'X': /* + X */
|
|
return start ? 0.6f : 0.7f;
|
|
case 'y': /* - Y */
|
|
return start ? 1.4f : 1.3f;
|
|
case 'Y': /* + Y */
|
|
return start ? 1.6f : 1.7f;
|
|
case 'z': /* - Z */
|
|
return start ? 2.4f : 2.3f;
|
|
case 'Z': /* + Z */
|
|
return start ? 2.6f : 2.7f;
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_groundline_get()
|
|
{
|
|
if (!SHC.drw_ground_line) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (1 + DIAMOND_NSEGMENTS);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
/* Ground Point */
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.35f, 0.0f, 0);
|
|
/* Ground Line */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, 1.0}, 0});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, 0.0}, 0});
|
|
|
|
SHC.drw_ground_line = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_ground_line;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_icon_inner_lines_get()
|
|
{
|
|
if (!SHC.drw_light_icon_inner_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (DIAMOND_NSEGMENTS + INNER_NSEGMENTS);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 9.0f;
|
|
int v = 0;
|
|
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, r * 0.3f, 0.0f, VCLASS_SCREENSPACE);
|
|
circle_dashed_verts(vbo, &v, INNER_NSEGMENTS, r * 1.0f, 0.0f, VCLASS_SCREENSPACE);
|
|
|
|
SHC.drw_light_icon_inner_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_icon_inner_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_icon_outer_lines_get()
|
|
{
|
|
if (!SHC.drw_light_icon_outer_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * OUTER_NSEGMENTS;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 9.0f;
|
|
int v = 0;
|
|
|
|
circle_dashed_verts(vbo, &v, OUTER_NSEGMENTS, r * 1.33f, 0.0f, VCLASS_SCREENSPACE);
|
|
|
|
SHC.drw_light_icon_outer_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_icon_outer_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_icon_sun_rays_get()
|
|
{
|
|
if (!SHC.drw_light_icon_sun_rays) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int num_rays = 8;
|
|
int v_len = 4 * num_rays;
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 9.0f;
|
|
|
|
int v = 0;
|
|
|
|
/* Sun Rays */
|
|
for (int a = 0; a < num_rays; a++) {
|
|
float angle = (2.0f * M_PI * a) / float(num_rays);
|
|
float s = sinf(angle) * r;
|
|
float c = cosf(angle) * r;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s * 1.6f, c * 1.6f, 0.0f}, VCLASS_SCREENSPACE});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s * 1.9f, c * 1.9f, 0.0f}, VCLASS_SCREENSPACE});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s * 2.2f, c * 2.2f, 0.0f}, VCLASS_SCREENSPACE});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s * 2.5f, c * 2.5f, 0.0f}, VCLASS_SCREENSPACE});
|
|
}
|
|
|
|
SHC.drw_light_icon_sun_rays = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_icon_sun_rays;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_point_lines_get()
|
|
{
|
|
if (!SHC.drw_light_point_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * CIRCLE_NSEGMENTS;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
|
|
/* Light area */
|
|
int flag = VCLASS_SCREENALIGNED | VCLASS_LIGHT_AREA_SHAPE;
|
|
circle_verts(vbo, &v, CIRCLE_NSEGMENTS, 1.0f, 0.0f, flag);
|
|
|
|
SHC.drw_light_point_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_point_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_sun_lines_get()
|
|
{
|
|
if (!SHC.drw_light_sun_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
|
|
/* Direction Line */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, 0.0}, 0});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, -20.0}, 0}); /* Good default. */
|
|
|
|
SHC.drw_light_sun_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_sun_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_spot_lines_get()
|
|
{
|
|
if (!SHC.drw_light_spot_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (DIAMOND_NSEGMENTS * 2 + CIRCLE_NSEGMENTS * 4 + 1);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
|
|
/* Light area */
|
|
int flag = VCLASS_SCREENALIGNED | VCLASS_LIGHT_AREA_SHAPE;
|
|
circle_verts(vbo, &v, CIRCLE_NSEGMENTS, 1.0f, 0.0f, flag);
|
|
/* Cone cap */
|
|
flag = VCLASS_LIGHT_SPOT_SHAPE;
|
|
circle_verts(vbo, &v, CIRCLE_NSEGMENTS, 1.0f, 0.0f, flag);
|
|
flag = VCLASS_LIGHT_SPOT_SHAPE | VCLASS_LIGHT_SPOT_BLEND;
|
|
circle_verts(vbo, &v, CIRCLE_NSEGMENTS, 1.0f, 0.0f, flag);
|
|
/* Cone silhouette */
|
|
flag = VCLASS_LIGHT_SPOT_SHAPE | VCLASS_LIGHT_SPOT_CONE;
|
|
for (int a = 0; a < CIRCLE_NSEGMENTS; a++) {
|
|
float angle = (2.0f * M_PI * a) / CIRCLE_NSEGMENTS;
|
|
float s = sinf(angle);
|
|
float c = cosf(angle);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.0f}, 0});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s, c, -1.0f}, flag});
|
|
}
|
|
/* Direction Line */
|
|
float zsta = light_distance_z_get('z', true);
|
|
float zend = light_distance_z_get('z', false);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zsta}, VCLASS_LIGHT_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zend}, VCLASS_LIGHT_DIST});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zsta, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zend, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
|
|
SHC.drw_light_spot_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_spot_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_spot_volume_get()
|
|
{
|
|
if (!SHC.drw_light_spot_volume) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = CIRCLE_NSEGMENTS + 1 + 1;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
/* Cone apex */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.0f}, 0});
|
|
/* Cone silhouette */
|
|
int flag = VCLASS_LIGHT_SPOT_SHAPE;
|
|
for (int a = 0; a < CIRCLE_NSEGMENTS + 1; a++) {
|
|
float angle = (2.0f * M_PI * a) / CIRCLE_NSEGMENTS;
|
|
float s = sinf(-angle);
|
|
float c = cosf(-angle);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{s, c, -1.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_light_spot_volume = GPU_batch_create_ex(
|
|
GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_spot_volume;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_area_disk_lines_get()
|
|
{
|
|
if (!SHC.drw_light_area_disk_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * (DIAMOND_NSEGMENTS * 2 + CIRCLE_NSEGMENTS + 1);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
|
|
/* Light area */
|
|
circle_verts(vbo, &v, CIRCLE_NSEGMENTS, 0.5f, 0.0f, VCLASS_LIGHT_AREA_SHAPE);
|
|
/* Direction Line */
|
|
float zsta = light_distance_z_get('z', true);
|
|
float zend = light_distance_z_get('z', false);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zsta}, VCLASS_LIGHT_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zend}, VCLASS_LIGHT_DIST});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zsta, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zend, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
|
|
SHC.drw_light_area_disk_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_area_disk_lines;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_light_area_square_lines_get()
|
|
{
|
|
if (!SHC.drw_light_area_square_lines) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
int v_len = 2 * (DIAMOND_NSEGMENTS * 2 + 4 + 1);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
|
|
/* Light area */
|
|
int flag = VCLASS_LIGHT_AREA_SHAPE;
|
|
for (int a = 0; a < 4; a++) {
|
|
for (int b = 0; b < 2; b++) {
|
|
const float p[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
|
|
float x = p[(a + b) % 4][0];
|
|
float y = p[(a + b) % 4][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x * 0.5f, y * 0.5f, 0.0f}, flag});
|
|
}
|
|
}
|
|
/* Direction Line */
|
|
float zsta = light_distance_z_get('z', true);
|
|
float zend = light_distance_z_get('z', false);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zsta}, VCLASS_LIGHT_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, zend}, VCLASS_LIGHT_DIST});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zsta, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zend, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
|
|
|
|
SHC.drw_light_area_square_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_light_area_square_lines;
|
|
}
|
|
|
|
#undef CIRCLE_NSEGMENTS
|
|
#undef OUTER_NSEGMENTS
|
|
#undef INNER_NSEGMENTS
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Speaker
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_speaker_get()
|
|
{
|
|
if (!SHC.drw_speaker) {
|
|
float v[3];
|
|
const int segments = 16;
|
|
int vidx = 0;
|
|
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 3 * segments * 2 + 4 * 4);
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
float z = 0.25f * j - 0.125f;
|
|
float r = (j == 0 ? 0.5f : 0.25f);
|
|
|
|
copy_v3_fl3(v, r, 0.0f, z);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
for (int i = 1; i < segments; i++) {
|
|
float x = cosf(2.0f * float(M_PI) * i / segments) * r;
|
|
float y = sinf(2.0f * float(M_PI) * i / segments) * r;
|
|
copy_v3_fl3(v, x, y, z);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
}
|
|
copy_v3_fl3(v, r, 0.0f, z);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
}
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
|
|
float y = ((j % 2) * (j - 2)) * 0.5f;
|
|
for (int i = 0; i < 3; i++) {
|
|
if (i == 1) {
|
|
x *= 0.5f;
|
|
y *= 0.5f;
|
|
}
|
|
|
|
float z = 0.25f * i - 0.125f;
|
|
copy_v3_fl3(v, x, y, z);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
if (i == 1) {
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
SHC.drw_speaker = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_speaker;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Probe
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_lightprobe_cube_get()
|
|
{
|
|
if (!SHC.drw_lightprobe_cube) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = (6 + 3 + (1 + 2 * DIAMOND_NSEGMENTS) * 6) * 2;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 14.0f;
|
|
int v = 0;
|
|
int flag = VCLASS_SCREENSPACE;
|
|
/* Icon */
|
|
const float sin_pi_3 = 0.86602540378f;
|
|
const float cos_pi_3 = 0.5f;
|
|
const float p[7][2] = {
|
|
{0.0f, 1.0f},
|
|
{sin_pi_3, cos_pi_3},
|
|
{sin_pi_3, -cos_pi_3},
|
|
{0.0f, -1.0f},
|
|
{-sin_pi_3, -cos_pi_3},
|
|
{-sin_pi_3, cos_pi_3},
|
|
{0.0f, 0.0f},
|
|
};
|
|
for (int i = 0; i < 6; i++) {
|
|
float t1[2], t2[2];
|
|
copy_v2_v2(t1, p[i]);
|
|
copy_v2_v2(t2, p[(i + 1) % 6]);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t1[0] * r, t1[1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t2[0] * r, t2[1] * r, 0.0f}, flag});
|
|
}
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[1][0] * r, p[1][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[5][0] * r, p[5][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[3][0] * r, p[3][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
/* Direction Lines */
|
|
flag = VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE;
|
|
for (int i = 0; i < 6; i++) {
|
|
char axes[] = "zZyYxX";
|
|
float zsta = light_distance_z_get(axes[i], true);
|
|
float zend = light_distance_z_get(axes[i], false);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, zsta}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, zend}, flag});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zsta, flag);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zend, flag);
|
|
}
|
|
|
|
SHC.drw_lightprobe_cube = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_lightprobe_cube;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lightprobe_grid_get()
|
|
{
|
|
if (!SHC.drw_lightprobe_grid) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = (6 * 2 + 3 + (1 + 2 * DIAMOND_NSEGMENTS) * 6) * 2;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 14.0f;
|
|
int v = 0;
|
|
int flag = VCLASS_SCREENSPACE;
|
|
/* Icon */
|
|
const float sin_pi_3 = 0.86602540378f;
|
|
const float cos_pi_3 = 0.5f;
|
|
const float p[7][2] = {
|
|
{0.0f, 1.0f},
|
|
{sin_pi_3, cos_pi_3},
|
|
{sin_pi_3, -cos_pi_3},
|
|
{0.0f, -1.0f},
|
|
{-sin_pi_3, -cos_pi_3},
|
|
{-sin_pi_3, cos_pi_3},
|
|
{0.0f, 0.0f},
|
|
};
|
|
for (int i = 0; i < 6; i++) {
|
|
float t1[2], t2[2], tr[2];
|
|
copy_v2_v2(t1, p[i]);
|
|
copy_v2_v2(t2, p[(i + 1) % 6]);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t1[0] * r, t1[1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t2[0] * r, t2[1] * r, 0.0f}, flag});
|
|
/* Internal wires. */
|
|
for (int j = 1; j < 2; j++) {
|
|
mul_v2_v2fl(tr, p[(i / 2) * 2 + 1], -0.5f * j);
|
|
add_v2_v2v2(t1, p[i], tr);
|
|
add_v2_v2v2(t2, p[(i + 1) % 6], tr);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t1[0] * r, t1[1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{t2[0] * r, t2[1] * r, 0.0f}, flag});
|
|
}
|
|
}
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[1][0] * r, p[1][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[5][0] * r, p[5][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[3][0] * r, p[3][1] * r, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[6][0] * r, p[6][1] * r, 0.0f}, flag});
|
|
/* Direction Lines */
|
|
flag = VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE;
|
|
for (int i = 0; i < 6; i++) {
|
|
char axes[] = "zZyYxX";
|
|
float zsta = light_distance_z_get(axes[i], true);
|
|
float zend = light_distance_z_get(axes[i], false);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, zsta}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, zend}, flag});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zsta, flag);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.2f, zend, flag);
|
|
}
|
|
|
|
SHC.drw_lightprobe_grid = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_lightprobe_grid;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lightprobe_planar_get()
|
|
{
|
|
if (!SHC.drw_lightprobe_planar) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
int v_len = 2 * 4;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
const float r = 20.0f;
|
|
int v = 0;
|
|
/* Icon */
|
|
const float sin_pi_3 = 0.86602540378f;
|
|
const float p[4][2] = {
|
|
{0.0f, 0.5f},
|
|
{sin_pi_3, 0.0f},
|
|
{0.0f, -0.5f},
|
|
{-sin_pi_3, 0.0f},
|
|
};
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int a = 0; a < 2; a++) {
|
|
float x = p[(i + a) % 4][0] * r;
|
|
float y = p[(i + a) % 4][1] * r;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 0.0}, VCLASS_SCREENSPACE});
|
|
}
|
|
}
|
|
|
|
SHC.drw_lightprobe_planar = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_lightprobe_planar;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Armature Bones
|
|
* \{ */
|
|
|
|
static const float bone_octahedral_verts[6][3] = {
|
|
{0.0f, 0.0f, 0.0f},
|
|
{0.1f, 0.1f, 0.1f},
|
|
{0.1f, 0.1f, -0.1f},
|
|
{-0.1f, 0.1f, -0.1f},
|
|
{-0.1f, 0.1f, 0.1f},
|
|
{0.0f, 1.0f, 0.0f},
|
|
};
|
|
|
|
#if 0 /* UNUSED */
|
|
|
|
static const uint bone_octahedral_wire[24] = {
|
|
0, 1, 1, 5, 5, 3, 3, 0, 0, 4, 4, 5, 5, 2, 2, 0, 1, 2, 2, 3, 3, 4, 4, 1,
|
|
};
|
|
|
|
/* aligned with bone_octahedral_wire
|
|
* Contains adjacent normal index */
|
|
static const uint bone_octahedral_wire_adjacent_face[24] = {
|
|
0, 3, 4, 7, 5, 6, 1, 2, 2, 3, 6, 7, 4, 5, 0, 1, 0, 4, 1, 5, 2, 6, 3, 7,
|
|
};
|
|
#endif
|
|
|
|
static const uint bone_octahedral_solid_tris[8][3] = {
|
|
{2, 1, 0}, /* bottom */
|
|
{3, 2, 0},
|
|
{4, 3, 0},
|
|
{1, 4, 0},
|
|
|
|
{5, 1, 2}, /* top */
|
|
{5, 2, 3},
|
|
{5, 3, 4},
|
|
{5, 4, 1},
|
|
};
|
|
|
|
/**
|
|
* Store indices of generated verts from bone_octahedral_solid_tris to define adjacency infos.
|
|
* Example: triangle {2, 1, 0} is adjacent to {3, 2, 0}, {1, 4, 0} and {5, 1, 2}.
|
|
* {2, 1, 0} becomes {0, 1, 2}
|
|
* {3, 2, 0} becomes {3, 4, 5}
|
|
* {1, 4, 0} becomes {9, 10, 11}
|
|
* {5, 1, 2} becomes {12, 13, 14}
|
|
* According to opengl specification it becomes (starting from
|
|
* the first vertex of the first face aka. vertex 2):
|
|
* {0, 12, 1, 10, 2, 3}
|
|
*/
|
|
static const uint bone_octahedral_wire_lines_adjacency[12][4] = {
|
|
{0, 1, 2, 6},
|
|
{0, 12, 1, 6},
|
|
{0, 3, 12, 6},
|
|
{0, 2, 3, 6},
|
|
{1, 6, 2, 3},
|
|
{1, 12, 6, 3},
|
|
{1, 0, 12, 3},
|
|
{1, 2, 0, 3},
|
|
{2, 0, 1, 12},
|
|
{2, 3, 0, 12},
|
|
{2, 6, 3, 12},
|
|
{2, 1, 6, 12},
|
|
};
|
|
|
|
#if 0 /* UNUSED */
|
|
static const uint bone_octahedral_solid_tris_adjacency[8][6] = {
|
|
{0, 12, 1, 10, 2, 3},
|
|
{3, 15, 4, 1, 5, 6},
|
|
{6, 18, 7, 4, 8, 9},
|
|
{9, 21, 10, 7, 11, 0},
|
|
|
|
{12, 22, 13, 2, 14, 17},
|
|
{15, 13, 16, 5, 17, 20},
|
|
{18, 16, 19, 8, 20, 23},
|
|
{21, 19, 22, 11, 23, 14},
|
|
};
|
|
#endif
|
|
|
|
/* aligned with bone_octahedral_solid_tris */
|
|
static const float bone_octahedral_solid_normals[8][3] = {
|
|
{M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
|
|
{-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
|
|
{-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
|
|
{0.00000000f, -M_SQRT1_2, M_SQRT1_2},
|
|
{0.99388373f, 0.11043154f, -0.00000000f},
|
|
{0.00000000f, 0.11043154f, -0.99388373f},
|
|
{-0.99388373f, 0.11043154f, 0.00000000f},
|
|
{0.00000000f, 0.11043154f, 0.99388373f},
|
|
};
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_octahedral_get()
|
|
{
|
|
if (!SHC.drw_bone_octahedral) {
|
|
uint v_idx = 0;
|
|
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, nor;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
/* Vertices */
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 24);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
|
|
GPU_vertbuf_attr_set(
|
|
vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]);
|
|
}
|
|
}
|
|
|
|
SHC.drw_bone_octahedral = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_octahedral;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_octahedral_wire_get()
|
|
{
|
|
if (!SHC.drw_bone_octahedral_wire) {
|
|
GPUIndexBufBuilder elb;
|
|
GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 24);
|
|
|
|
for (int i = 0; i < 12; i++) {
|
|
GPU_indexbuf_add_line_adj_verts(&elb,
|
|
bone_octahedral_wire_lines_adjacency[i][0],
|
|
bone_octahedral_wire_lines_adjacency[i][1],
|
|
bone_octahedral_wire_lines_adjacency[i][2],
|
|
bone_octahedral_wire_lines_adjacency[i][3]);
|
|
}
|
|
|
|
/* HACK Reuse vertex buffer. */
|
|
blender::gpu::Batch *pos_nor_batch = DRW_cache_bone_octahedral_get();
|
|
|
|
SHC.drw_bone_octahedral_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ,
|
|
pos_nor_batch->verts[0],
|
|
GPU_indexbuf_build(&elb),
|
|
GPU_BATCH_OWNS_INDEX);
|
|
}
|
|
return SHC.drw_bone_octahedral_wire;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_box_get()
|
|
{
|
|
if (!SHC.drw_bone_box) {
|
|
uint v_idx = 0;
|
|
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, nor;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
/* Vertices */
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 36);
|
|
|
|
for (int i = 0; i < 12; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
|
|
}
|
|
}
|
|
|
|
SHC.drw_bone_box = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_box;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_box_wire_get()
|
|
{
|
|
if (!SHC.drw_bone_box_wire) {
|
|
GPUIndexBufBuilder elb;
|
|
GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 36);
|
|
|
|
for (int i = 0; i < 12; i++) {
|
|
GPU_indexbuf_add_line_adj_verts(&elb,
|
|
bone_box_wire_lines_adjacency[i][0],
|
|
bone_box_wire_lines_adjacency[i][1],
|
|
bone_box_wire_lines_adjacency[i][2],
|
|
bone_box_wire_lines_adjacency[i][3]);
|
|
}
|
|
|
|
/* HACK Reuse vertex buffer. */
|
|
blender::gpu::Batch *pos_nor_batch = DRW_cache_bone_box_get();
|
|
|
|
SHC.drw_bone_box_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ,
|
|
pos_nor_batch->verts[0],
|
|
GPU_indexbuf_build(&elb),
|
|
GPU_BATCH_OWNS_INDEX);
|
|
}
|
|
return SHC.drw_bone_box_wire;
|
|
}
|
|
|
|
/* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder.
|
|
* Note that here we only encode head/tail in forth component of the vector. */
|
|
static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3])
|
|
{
|
|
r_nor[0] = sinf(lat) * cosf(lon);
|
|
r_nor[1] = sinf(lat) * sinf(lon);
|
|
r_nor[2] = cosf(lat);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_envelope_solid_get()
|
|
{
|
|
if (!SHC.drw_bone_envelope) {
|
|
const int lon_res = 24;
|
|
const int lat_res = 24;
|
|
const float lon_inc = 2.0f * M_PI / lon_res;
|
|
const float lat_inc = M_PI / lat_res;
|
|
uint v_idx = 0;
|
|
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
/* Vertices */
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, ((lat_res + 1) * 2) * lon_res * 1);
|
|
|
|
float lon = 0.0f;
|
|
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
|
|
float lat = 0.0f;
|
|
float co1[3], co2[3];
|
|
|
|
/* NOTE: the poles are duplicated on purpose, to restart the strip. */
|
|
|
|
/* 1st sphere */
|
|
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
|
|
benv_lat_lon_to_co(lat, lon, co1);
|
|
benv_lat_lon_to_co(lat, lon + lon_inc, co2);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
|
|
}
|
|
|
|
/* Closing the loop */
|
|
benv_lat_lon_to_co(M_PI, lon, co1);
|
|
benv_lat_lon_to_co(M_PI, lon + lon_inc, co2);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
|
|
}
|
|
|
|
SHC.drw_bone_envelope = GPU_batch_create_ex(
|
|
GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_envelope;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_envelope_outline_get()
|
|
{
|
|
if (!SHC.drw_bone_envelope_outline) {
|
|
#define CIRCLE_RESOL 64
|
|
float v0[2], v1[2], v2[2];
|
|
const float radius = 1.0f;
|
|
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos0, pos1, pos2;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos0 = GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
attr_id.pos1 = GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
attr_id.pos2 = GPU_vertformat_attr_add(&format, "pos2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, CIRCLE_RESOL + 1);
|
|
|
|
v0[0] = radius * sinf((2.0f * M_PI * -2) / float(CIRCLE_RESOL));
|
|
v0[1] = radius * cosf((2.0f * M_PI * -2) / float(CIRCLE_RESOL));
|
|
v1[0] = radius * sinf((2.0f * M_PI * -1) / float(CIRCLE_RESOL));
|
|
v1[1] = radius * cosf((2.0f * M_PI * -1) / float(CIRCLE_RESOL));
|
|
|
|
/* Output 4 verts for each position. See shader for explanation. */
|
|
uint v = 0;
|
|
for (int a = 0; a <= CIRCLE_RESOL; a++) {
|
|
v2[0] = radius * sinf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
v2[1] = radius * cosf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos0, v, v0);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos1, v, v1);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
|
|
copy_v2_v2(v0, v1);
|
|
copy_v2_v2(v1, v2);
|
|
}
|
|
|
|
SHC.drw_bone_envelope_outline = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
return SHC.drw_bone_envelope_outline;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_point_get()
|
|
{
|
|
if (!SHC.drw_bone_point) {
|
|
#if 0 /* old style geometry sphere */
|
|
const int lon_res = 16;
|
|
const int lat_res = 8;
|
|
const float rad = 0.05f;
|
|
const float lon_inc = 2 * M_PI / lon_res;
|
|
const float lat_inc = M_PI / lat_res;
|
|
uint v_idx = 0;
|
|
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, nor;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
/* Vertices */
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, (lat_res - 1) * lon_res * 6);
|
|
|
|
float lon = 0.0f;
|
|
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
|
|
float lat = 0.0f;
|
|
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
|
|
if (j != lat_res - 1) { /* Pole */
|
|
add_lat_lon_vert(
|
|
vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
|
|
add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon);
|
|
add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon);
|
|
}
|
|
|
|
if (j != 0) { /* Pole */
|
|
add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon + lon_inc);
|
|
add_lat_lon_vert(
|
|
vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
|
|
add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon);
|
|
}
|
|
}
|
|
}
|
|
|
|
SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
#else
|
|
# define CIRCLE_RESOL 64
|
|
float v[2];
|
|
const float radius = 0.05f;
|
|
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, CIRCLE_RESOL);
|
|
|
|
for (int a = 0; a < CIRCLE_RESOL; a++) {
|
|
v[0] = radius * sinf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
v[1] = radius * cosf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
|
|
}
|
|
|
|
SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
# undef CIRCLE_RESOL
|
|
#endif
|
|
}
|
|
return SHC.drw_bone_point;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_point_wire_outline_get()
|
|
{
|
|
if (!SHC.drw_bone_point_wire) {
|
|
#if 0 /* old style geometry sphere */
|
|
blender::gpu::VertBuf *vbo = sphere_wire_vbo(0.05f);
|
|
SHC.drw_bone_point_wire = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
#else
|
|
# define CIRCLE_RESOL 64
|
|
const float radius = 0.05f;
|
|
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, CIRCLE_RESOL + 1);
|
|
|
|
uint v = 0;
|
|
for (int a = 0; a <= CIRCLE_RESOL; a++) {
|
|
float pos[2];
|
|
pos[0] = radius * sinf((2.0f * M_PI * a) / CIRCLE_RESOL);
|
|
pos[1] = radius * cosf((2.0f * M_PI * a) / CIRCLE_RESOL);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v++, pos);
|
|
}
|
|
|
|
SHC.drw_bone_point_wire = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
# undef CIRCLE_RESOL
|
|
#endif
|
|
}
|
|
return SHC.drw_bone_point_wire;
|
|
}
|
|
|
|
/* keep in sync with armature_stick_vert.glsl */
|
|
#define COL_WIRE (1 << 0)
|
|
#define COL_HEAD (1 << 1)
|
|
#define COL_TAIL (1 << 2)
|
|
#define COL_BONE (1 << 3)
|
|
|
|
#define POS_HEAD (1 << 4)
|
|
#define POS_TAIL (1 << 5)
|
|
#define POS_BONE (1 << 6)
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_stick_get()
|
|
{
|
|
if (!SHC.drw_bone_stick) {
|
|
#define CIRCLE_RESOL 12
|
|
uint v = 0;
|
|
uint flag;
|
|
const float radius = 2.0f; /* head/tail radius */
|
|
float pos[2];
|
|
|
|
/* Position Only 2D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, flag;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
attr_id.flag = GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
|
}
|
|
|
|
const uint vcount = (CIRCLE_RESOL + 1) * 2 + 6;
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, vcount);
|
|
|
|
GPUIndexBufBuilder elb;
|
|
GPU_indexbuf_init_ex(&elb, GPU_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount);
|
|
|
|
/* head/tail points */
|
|
for (int i = 0; i < 2; i++) {
|
|
/* center vertex */
|
|
copy_v2_fl(pos, 0.0f);
|
|
flag = (i == 0) ? POS_HEAD : POS_TAIL;
|
|
flag |= (i == 0) ? COL_HEAD : COL_TAIL;
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
/* circle vertices */
|
|
flag |= COL_WIRE;
|
|
for (int a = 0; a < CIRCLE_RESOL; a++) {
|
|
pos[0] = radius * sinf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
pos[1] = radius * cosf((2.0f * M_PI * a) / float(CIRCLE_RESOL));
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
}
|
|
/* Close the circle */
|
|
GPU_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL);
|
|
|
|
GPU_indexbuf_add_primitive_restart(&elb);
|
|
}
|
|
|
|
/* Bone rectangle */
|
|
pos[0] = 0.0f;
|
|
for (int i = 0; i < 6; i++) {
|
|
pos[1] = ELEM(i, 0, 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f);
|
|
flag = ((i < 2 || i > 4) ? POS_HEAD : POS_TAIL) | (ELEM(i, 0, 3) ? 0 : COL_WIRE) | COL_BONE |
|
|
POS_BONE;
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, pos);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
}
|
|
|
|
SHC.drw_bone_stick = GPU_batch_create_ex(GPU_PRIM_TRI_FAN,
|
|
vbo,
|
|
GPU_indexbuf_build(&elb),
|
|
GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
|
#undef CIRCLE_RESOL
|
|
}
|
|
return SHC.drw_bone_stick;
|
|
}
|
|
|
|
#define S_X 0.0215f
|
|
#define S_Y 0.025f
|
|
static float x_axis_name[4][2] = {
|
|
{0.9f * S_X, 1.0f * S_Y},
|
|
{-1.0f * S_X, -1.0f * S_Y},
|
|
{-0.9f * S_X, 1.0f * S_Y},
|
|
{1.0f * S_X, -1.0f * S_Y},
|
|
};
|
|
#define X_LEN ARRAY_SIZE(x_axis_name)
|
|
#undef S_X
|
|
#undef S_Y
|
|
|
|
#define S_X 0.0175f
|
|
#define S_Y 0.025f
|
|
static float y_axis_name[6][2] = {
|
|
{-1.0f * S_X, 1.0f * S_Y},
|
|
{0.0f * S_X, -0.1f * S_Y},
|
|
{1.0f * S_X, 1.0f * S_Y},
|
|
{0.0f * S_X, -0.1f * S_Y},
|
|
{0.0f * S_X, -0.1f * S_Y},
|
|
{0.0f * S_X, -1.0f * S_Y},
|
|
};
|
|
#define Y_LEN ARRAY_SIZE(y_axis_name)
|
|
#undef S_X
|
|
#undef S_Y
|
|
|
|
#define S_X 0.02f
|
|
#define S_Y 0.025f
|
|
static float z_axis_name[10][2] = {
|
|
{-0.95f * S_X, 1.00f * S_Y},
|
|
{0.95f * S_X, 1.00f * S_Y},
|
|
{0.95f * S_X, 1.00f * S_Y},
|
|
{0.95f * S_X, 0.90f * S_Y},
|
|
{0.95f * S_X, 0.90f * S_Y},
|
|
{-1.00f * S_X, -0.90f * S_Y},
|
|
{-1.00f * S_X, -0.90f * S_Y},
|
|
{-1.00f * S_X, -1.00f * S_Y},
|
|
{-1.00f * S_X, -1.00f * S_Y},
|
|
{1.00f * S_X, -1.00f * S_Y},
|
|
};
|
|
#define Z_LEN ARRAY_SIZE(z_axis_name)
|
|
#undef S_X
|
|
#undef S_Y
|
|
|
|
#define S_X 0.007f
|
|
#define S_Y 0.007f
|
|
static float axis_marker[8][2] = {
|
|
#if 0 /* square */
|
|
{-1.0f * S_X, 1.0f * S_Y},
|
|
{1.0f * S_X, 1.0f * S_Y},
|
|
{1.0f * S_X, 1.0f * S_Y},
|
|
{1.0f * S_X, -1.0f * S_Y},
|
|
{1.0f * S_X, -1.0f * S_Y},
|
|
{-1.0f * S_X, -1.0f * S_Y},
|
|
{-1.0f * S_X, -1.0f * S_Y},
|
|
{-1.0f * S_X, 1.0f * S_Y}
|
|
#else /* diamond */
|
|
{-S_X, 0.0f},
|
|
{0.0f, S_Y},
|
|
{0.0f, S_Y},
|
|
{S_X, 0.0f},
|
|
{S_X, 0.0f},
|
|
{0.0f, -S_Y},
|
|
{0.0f, -S_Y},
|
|
{-S_X, 0.0f}
|
|
#endif
|
|
};
|
|
#define MARKER_LEN ARRAY_SIZE(axis_marker)
|
|
#define MARKER_FILL_LAYER 6
|
|
#undef S_X
|
|
#undef S_Y
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_arrows_get()
|
|
{
|
|
if (!SHC.drw_bone_arrows) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
int v_len = (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 + (X_LEN + Y_LEN + Z_LEN);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
for (int axis = 0; axis < 3; axis++) {
|
|
int flag = VCLASS_EMPTY_AXES | VCLASS_SCREENALIGNED;
|
|
/* Vertex layout is XY screen position and axis in Z.
|
|
* Fractional part of Z is a positive offset at axis unit position. */
|
|
float p[3] = {0.0f, 0.0f, float(axis)};
|
|
/* center to axis line */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.0f}, 0});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[0], p[1], p[2]}, flag});
|
|
/* Axis end marker */
|
|
for (int j = 1; j < MARKER_FILL_LAYER + 1; j++) {
|
|
for (int i = 0; i < MARKER_LEN; i++) {
|
|
mul_v2_v2fl(p, axis_marker[i], 4.0f * j / float(MARKER_FILL_LAYER));
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[0], p[1], p[2]}, flag});
|
|
}
|
|
}
|
|
/* Axis name */
|
|
flag = VCLASS_EMPTY_AXES | VCLASS_EMPTY_AXES_NAME | VCLASS_SCREENALIGNED;
|
|
int axis_v_len[] = {X_LEN, Y_LEN, Z_LEN};
|
|
float(*axis_v)[2] = (axis == 0) ? x_axis_name : ((axis == 1) ? y_axis_name : z_axis_name);
|
|
p[2] = axis + 0.25f;
|
|
for (int i = 0; i < axis_v_len[axis]; i++) {
|
|
mul_v2_v2fl(p, axis_v[i], 4.0f);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{p[0], p[1], p[2]}, flag});
|
|
}
|
|
}
|
|
|
|
SHC.drw_bone_arrows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_arrows;
|
|
}
|
|
|
|
static const float staticSine[16] = {
|
|
0.0f,
|
|
0.104528463268f,
|
|
0.207911690818f,
|
|
0.309016994375f,
|
|
0.406736643076f,
|
|
0.5f,
|
|
0.587785252292f,
|
|
0.669130606359f,
|
|
0.743144825477f,
|
|
0.809016994375f,
|
|
0.866025403784f,
|
|
0.913545457643f,
|
|
0.951056516295f,
|
|
0.978147600734f,
|
|
0.994521895368f,
|
|
1.0f,
|
|
};
|
|
|
|
#define set_vert(a, b, quarter) \
|
|
{ \
|
|
copy_v2_fl2(pos, (quarter % 2 == 0) ? -(a) : (a), (quarter < 2) ? -(b) : (b)); \
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v++, pos); \
|
|
} \
|
|
((void)0)
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_dof_sphere_get()
|
|
{
|
|
if (!SHC.drw_bone_dof_sphere) {
|
|
int i, j, q, n = ARRAY_SIZE(staticSine);
|
|
float x, z, px, pz, pos[2];
|
|
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, n * n * 6 * 4);
|
|
|
|
uint v = 0;
|
|
for (q = 0; q < 4; q++) {
|
|
pz = 0.0f;
|
|
for (i = 1; i < n; i++) {
|
|
z = staticSine[i];
|
|
px = 0.0f;
|
|
for (j = 1; j <= (n - i); j++) {
|
|
x = staticSine[j];
|
|
if (j == n - i) {
|
|
set_vert(px, z, q);
|
|
set_vert(px, pz, q);
|
|
set_vert(x, pz, q);
|
|
}
|
|
else {
|
|
set_vert(x, z, q);
|
|
set_vert(x, pz, q);
|
|
set_vert(px, z, q);
|
|
|
|
set_vert(x, pz, q);
|
|
set_vert(px, pz, q);
|
|
set_vert(px, z, q);
|
|
}
|
|
px = x;
|
|
}
|
|
pz = z;
|
|
}
|
|
}
|
|
/* TODO: allocate right count from the beginning. */
|
|
GPU_vertbuf_data_resize(*vbo, v);
|
|
|
|
SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_dof_sphere;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_bone_dof_lines_get()
|
|
{
|
|
if (!SHC.drw_bone_dof_lines) {
|
|
int i, n = ARRAY_SIZE(staticSine);
|
|
float pos[2];
|
|
|
|
/* Position Only 3D format */
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, n * 4);
|
|
|
|
uint v = 0;
|
|
for (i = 0; i < n * 4; i++) {
|
|
float a = (1.0f - (i / float(n * 4))) * 2.0f * M_PI;
|
|
float x = cosf(a);
|
|
float y = sinf(a);
|
|
set_vert(x, y, 0);
|
|
}
|
|
|
|
SHC.drw_bone_dof_lines = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_LOOP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_bone_dof_lines;
|
|
}
|
|
|
|
#undef set_vert
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Camera
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_frame_get()
|
|
{
|
|
if (!SHC.drw_camera_frame) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = 2 * (4 + 4);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
const float p[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
|
|
/* Frame */
|
|
for (int a = 0; a < 4; a++) {
|
|
for (int b = 0; b < 2; b++) {
|
|
float x = p[(a + b) % 4][0];
|
|
float y = p[(a + b) % 4][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
}
|
|
}
|
|
/* Wires to origin. */
|
|
for (int a = 0; a < 4; a++) {
|
|
float x = p[a][0];
|
|
float y = p[a][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 0.0f}, VCLASS_CAMERA_FRAME});
|
|
}
|
|
|
|
SHC.drw_camera_frame = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_frame;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_volume_get()
|
|
{
|
|
if (!SHC.drw_camera_volume) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = ARRAY_SIZE(bone_box_solid_tris) * 3;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_CAMERA_FRAME | VCLASS_CAMERA_VOLUME;
|
|
for (int i = 0; i < ARRAY_SIZE(bone_box_solid_tris); i++) {
|
|
for (int a = 0; a < 3; a++) {
|
|
float x = bone_box_verts[bone_box_solid_tris[i][a]][2];
|
|
float y = bone_box_verts[bone_box_solid_tris[i][a]][0];
|
|
float z = bone_box_verts[bone_box_solid_tris[i][a]][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, z}, flag});
|
|
}
|
|
}
|
|
|
|
SHC.drw_camera_volume = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_volume;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_volume_wire_get()
|
|
{
|
|
if (!SHC.drw_camera_volume_wire) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = ARRAY_SIZE(bone_box_wire);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_CAMERA_FRAME | VCLASS_CAMERA_VOLUME;
|
|
for (int i = 0; i < ARRAY_SIZE(bone_box_wire); i++) {
|
|
float x = bone_box_verts[bone_box_wire[i]][2];
|
|
float y = bone_box_verts[bone_box_wire[i]][0];
|
|
float z = bone_box_verts[bone_box_wire[i]][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, z}, flag});
|
|
}
|
|
|
|
SHC.drw_camera_volume_wire = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_volume_wire;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_tria_wire_get()
|
|
{
|
|
if (!SHC.drw_camera_tria_wire) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = 2 * 3;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
const float p[3][2] = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}};
|
|
for (int a = 0; a < 3; a++) {
|
|
for (int b = 0; b < 2; b++) {
|
|
float x = p[(a + b) % 3][0];
|
|
float y = p[(a + b) % 3][1];
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
}
|
|
}
|
|
|
|
SHC.drw_camera_tria_wire = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_tria_wire;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_tria_get()
|
|
{
|
|
if (!SHC.drw_camera_tria) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = 3;
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
/* Use camera frame position */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{-1.0f, 1.0f, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{1.0f, 1.0f, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 1.0f}, VCLASS_CAMERA_FRAME});
|
|
|
|
SHC.drw_camera_tria = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_tria;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_camera_distances_get()
|
|
{
|
|
if (!SHC.drw_camera_distances) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
|
|
const int v_len = 2 * (1 + DIAMOND_NSEGMENTS * 2 + 2);
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, v_len);
|
|
|
|
int v = 0;
|
|
/* Direction Line */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, 0.0}, VCLASS_CAMERA_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 0.0, 1.0}, VCLASS_CAMERA_DIST});
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.5f, 0.0f, VCLASS_CAMERA_DIST | VCLASS_SCREENSPACE);
|
|
circle_verts(vbo, &v, DIAMOND_NSEGMENTS, 1.5f, 1.0f, VCLASS_CAMERA_DIST | VCLASS_SCREENSPACE);
|
|
/* Focus cross */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{1.0, 0.0, 2.0}, VCLASS_CAMERA_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{-1.0, 0.0, 2.0}, VCLASS_CAMERA_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, 1.0, 2.0}, VCLASS_CAMERA_DIST});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0, -1.0, 2.0}, VCLASS_CAMERA_DIST});
|
|
|
|
SHC.drw_camera_distances = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
return SHC.drw_camera_distances;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Meshes
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_all_verts_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_all_verts(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_all_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_all_edges(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_loose_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_loose_edges(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_edge_detection(*static_cast<Mesh *>(ob->data), r_is_manifold);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_edges(*ob, *static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_mesh_surface_shaded_get(
|
|
Object *ob, const blender::Span<const GPUMaterial *> materials)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_shaded(*ob, *static_cast<Mesh *>(ob->data), materials);
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_mesh_surface_texpaint_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_texpaint(*ob, *static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_texpaint_single(*ob, *static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_vertpaint_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_vertpaint(*ob, *static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_sculpt(*ob, *static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_weights(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_face_wireframe_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_wireframes_face(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_edit_mesh_analysis(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_viewer_attribute_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_viewer_attribute(*static_cast<Mesh *>(ob->data));
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Curve
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_wire_edge(cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_wire_viewer_attribute_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_wire_edge_viewer_attribute(cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_normal_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_normal_edge(cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF));
|
|
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_edit_edges(cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF));
|
|
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_edit_verts(cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Font
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_text_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_FONT);
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_wire_edge(cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Surface
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_surf_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_SURF);
|
|
Curve *cu = static_cast<Curve *>(ob->data);
|
|
return DRW_curve_batch_cache_get_wire_edge(cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Lattice
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_verts_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice *lt = static_cast<Lattice *>(ob->data);
|
|
return DRW_lattice_batch_cache_get_all_verts(lt);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice *lt = static_cast<Lattice *>(ob->data);
|
|
int actdef = -1;
|
|
|
|
if (use_weight && !BLI_listbase_is_empty(<->vertex_group_names) && lt->editlatt->latt->dvert) {
|
|
actdef = lt->vertex_group_active_index - 1;
|
|
}
|
|
|
|
return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice *lt = static_cast<Lattice *>(ob->data);
|
|
return DRW_lattice_batch_cache_get_edit_verts(lt);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name PointCloud
|
|
* \{ */
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Volume
|
|
* \{ */
|
|
|
|
namespace blender::draw {
|
|
|
|
blender::gpu::Batch *DRW_cache_volume_face_wireframe_get(Object *ob)
|
|
{
|
|
BLI_assert(ob->type == OB_VOLUME);
|
|
return DRW_volume_batch_cache_get_wireframes_face(static_cast<Volume *>(ob->data));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_volume_selection_surface_get(Object *ob)
|
|
{
|
|
BLI_assert(ob->type == OB_VOLUME);
|
|
return DRW_volume_batch_cache_get_selection_surface(static_cast<Volume *>(ob->data));
|
|
}
|
|
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Particles
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_hair(Object *object,
|
|
ParticleSystem *psys,
|
|
ModifierData *md)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_hair(object, psys, md);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_dots(object, psys);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_strands(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit,
|
|
bool use_weight)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_strands(object, psys, edit, use_weight);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_inner_points(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_inner_points(object, psys, edit);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_tip_points(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_tip_points(object, psys, edit);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_prim(int type)
|
|
{
|
|
switch (type) {
|
|
case PART_DRAW_CROSS:
|
|
if (!SHC.drw_particle_cross) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 6);
|
|
|
|
int v = 0;
|
|
int flag = 0;
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, -1.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 1.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{-1.0f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{1.0f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, -1.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 1.0f}, flag});
|
|
|
|
SHC.drw_particle_cross = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
return SHC.drw_particle_cross;
|
|
case PART_DRAW_AXIS:
|
|
if (!SHC.drw_particle_axis) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, 6);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_EMPTY_AXES;
|
|
/* Set minimum to 0.001f so we can easily normalize to get the color. */
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0001f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 2.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0001f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{2.0f, 0.0f, 0.0f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 0.0001f}, flag});
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{0.0f, 0.0f, 2.0f}, flag});
|
|
|
|
SHC.drw_particle_axis = GPU_batch_create_ex(
|
|
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
return SHC.drw_particle_axis;
|
|
case PART_DRAW_CIRC:
|
|
#define CIRCLE_RESOL 32
|
|
if (!SHC.drw_particle_circle) {
|
|
GPUVertFormat format = extra_vert_format();
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, CIRCLE_RESOL + 1);
|
|
|
|
int v = 0;
|
|
int flag = VCLASS_SCREENALIGNED;
|
|
for (int a = 0; a <= CIRCLE_RESOL; a++) {
|
|
float angle = (2.0f * M_PI * a) / CIRCLE_RESOL;
|
|
float x = sinf(angle);
|
|
float y = cosf(angle);
|
|
GPU_vertbuf_vert_set(vbo, v++, Vert{{x, y, 0.0f}, flag});
|
|
}
|
|
|
|
SHC.drw_particle_circle = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
|
}
|
|
|
|
return SHC.drw_particle_circle;
|
|
#undef CIRCLE_RESOL
|
|
default:
|
|
BLI_assert(false);
|
|
break;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_cursor_get(bool crosshair_lines)
|
|
{
|
|
blender::gpu::Batch **drw_cursor = crosshair_lines ? &SHC.drw_cursor :
|
|
&SHC.drw_cursor_only_circle;
|
|
|
|
if (*drw_cursor == nullptr) {
|
|
const float f5 = 0.25f;
|
|
const float f10 = 0.5f;
|
|
const float f20 = 1.0f;
|
|
|
|
const int segments = 16;
|
|
const int vert_len = segments + 8;
|
|
const int index_len = vert_len + 5;
|
|
|
|
const float red[3] = {1.0f, 0.0f, 0.0f};
|
|
const float white[3] = {1.0f, 1.0f, 1.0f};
|
|
|
|
static GPUVertFormat format = {0};
|
|
static struct {
|
|
uint pos, color;
|
|
} attr_id;
|
|
if (format.attr_len == 0) {
|
|
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
attr_id.color = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
}
|
|
|
|
GPUIndexBufBuilder elb;
|
|
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
|
|
|
|
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
|
GPU_vertbuf_data_alloc(*vbo, vert_len);
|
|
|
|
int v = 0;
|
|
for (int i = 0; i < segments; i++) {
|
|
float angle = float(2 * M_PI) * (float(i) / float(segments));
|
|
float x = f10 * cosf(angle);
|
|
float y = f10 * sinf(angle);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, (i % 2 == 0) ? red : white);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{x, y});
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
}
|
|
GPU_indexbuf_add_generic_vert(&elb, 0);
|
|
|
|
if (crosshair_lines) {
|
|
float crosshair_color[3];
|
|
UI_GetThemeColor3fv(TH_VIEW_OVERLAY, crosshair_color);
|
|
|
|
/* TODO(fclem): Remove primitive restart. Incompatible with wide lines. */
|
|
GPU_indexbuf_add_primitive_restart(&elb);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{-f20, 0});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{-f5, 0});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
|
|
GPU_indexbuf_add_primitive_restart(&elb);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{+f5, 0});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{+f20, 0});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
|
|
GPU_indexbuf_add_primitive_restart(&elb);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{0, -f20});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{0, -f5});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
|
|
GPU_indexbuf_add_primitive_restart(&elb);
|
|
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{0, +f5});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
GPU_vertbuf_attr_set(vbo, attr_id.pos, v, blender::float2{0, +f20});
|
|
GPU_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color);
|
|
GPU_indexbuf_add_generic_vert(&elb, v++);
|
|
}
|
|
|
|
blender::gpu::IndexBuf *ibo = GPU_indexbuf_build(&elb);
|
|
|
|
*drw_cursor = GPU_batch_create_ex(
|
|
GPU_PRIM_LINE_STRIP, vbo, ibo, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
|
}
|
|
return *drw_cursor;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Batch Cache Implementation (common)
|
|
* \{ */
|
|
|
|
void drw_batch_cache_validate(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_validate(*(Mesh *)ob->data);
|
|
break;
|
|
case OB_CURVES_LEGACY:
|
|
case OB_FONT:
|
|
case OB_SURF:
|
|
DRW_curve_batch_cache_validate((Curve *)ob->data);
|
|
break;
|
|
case OB_LATTICE:
|
|
DRW_lattice_batch_cache_validate((Lattice *)ob->data);
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_validate((Curves *)ob->data);
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_validate((PointCloud *)ob->data);
|
|
break;
|
|
case OB_VOLUME:
|
|
DRW_volume_batch_cache_validate((Volume *)ob->data);
|
|
break;
|
|
case OB_GREASE_PENCIL:
|
|
DRW_grease_pencil_batch_cache_validate((GreasePencil *)ob->data);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
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(
|
|
mode, CTX_MODE_SCULPT, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
|
|
|
|
const bool use_hide = ((ob->type == OB_MESH) &&
|
|
((is_paint_mode && (ob == draw_ctx->obact) &&
|
|
DRW_object_use_hide_faces(ob)) ||
|
|
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
|
|
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_create_requested(
|
|
*DST.task_graph, *ob, *(Mesh *)ob->data, *scene, is_paint_mode, use_hide);
|
|
break;
|
|
case OB_CURVES_LEGACY:
|
|
case OB_FONT:
|
|
case OB_SURF:
|
|
DRW_curve_batch_cache_create_requested(ob, scene);
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_create_requested(ob);
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_create_requested(ob);
|
|
break;
|
|
/* TODO: all cases. */
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested_evaluated_mesh_or_curve(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
/* NOTE: Logic here is duplicated from #drw_batch_cache_generate_requested. */
|
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
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(
|
|
mode, CTX_MODE_SCULPT, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
|
|
|
|
const bool use_hide = ((ob->type == OB_MESH) &&
|
|
((is_paint_mode && (ob == draw_ctx->obact) &&
|
|
DRW_object_use_hide_faces(ob)) ||
|
|
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
|
|
|
|
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(ob);
|
|
/* Try getting the mesh first and if that fails, try getting the curve data.
|
|
* If the curves are surfaces or have certain modifiers applied to them, the will have mesh data
|
|
* of the final result.
|
|
*/
|
|
if (mesh != nullptr) {
|
|
DRW_mesh_batch_cache_create_requested(
|
|
*DST.task_graph, *ob, *mesh, *scene, is_paint_mode, use_hide);
|
|
}
|
|
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
|
|
DRW_curve_batch_cache_create_requested(ob, scene);
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested_delayed(Object *ob)
|
|
{
|
|
BLI_gset_add(DST.delayed_extraction, ob);
|
|
}
|
|
|
|
namespace blender::draw {
|
|
void DRW_batch_cache_free_old(Object *ob, int ctime)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_free_old((Mesh *)ob->data, ctime);
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_free_old((Curves *)ob->data, ctime);
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_free_old((PointCloud *)ob->data, ctime);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
void DRW_cdlayer_attr_aliases_add(GPUVertFormat *format,
|
|
const char *base_name,
|
|
const int data_type,
|
|
const char *layer_name,
|
|
bool is_active_render,
|
|
bool is_active_layer)
|
|
{
|
|
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
|
|
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
|
|
|
|
/* Attribute layer name. */
|
|
SNPRINTF(attr_name, "%s%s", base_name, attr_safe_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
|
|
/* Auto layer name. */
|
|
SNPRINTF(attr_name, "a%s", attr_safe_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
|
|
/* Active render layer name. */
|
|
if (is_active_render) {
|
|
GPU_vertformat_alias_add(format, data_type == CD_PROP_FLOAT2 ? "a" : base_name);
|
|
}
|
|
|
|
/* Active display layer name. */
|
|
if (is_active_layer) {
|
|
SNPRINTF(attr_name, "a%s", base_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
}
|
|
}
|