Files
test/source/blender/draw/intern/draw_cache.c
Luca Rood 20f95de6ba Weight painting with draw manager
This implements weight rendering with the draw manager, with all drawing
options (Shading, wire, face masking, vertex masking).

This is part of T51208

Reviewers: campbellbarton

Subscribers: dfelinto

Differential Revision: https://developer.blender.org/D2654
2017-05-03 18:57:35 +02:00

1970 lines
54 KiB
C

/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file draw_cache.c
* \ingroup draw
*/
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "GPU_batch.h"
#include "draw_cache.h"
#include "draw_cache_impl.h"
static struct DRWShapeCache {
Batch *drw_single_vertice;
Batch *drw_fullscreen_quad;
Batch *drw_screenspace_circle;
Batch *drw_plain_axes;
Batch *drw_single_arrow;
Batch *drw_cube;
Batch *drw_circle;
Batch *drw_square;
Batch *drw_line;
Batch *drw_line_endpoints;
Batch *drw_empty_sphere;
Batch *drw_empty_cone;
Batch *drw_arrows;
Batch *drw_axis_names;
Batch *drw_field_wind;
Batch *drw_field_force;
Batch *drw_field_vortex;
Batch *drw_field_tube_limit;
Batch *drw_field_cone_limit;
Batch *drw_lamp;
Batch *drw_lamp_sunrays;
Batch *drw_lamp_area;
Batch *drw_lamp_hemi;
Batch *drw_lamp_spot;
Batch *drw_lamp_spot_square;
Batch *drw_speaker;
Batch *drw_bone_octahedral;
Batch *drw_bone_octahedral_wire;
Batch *drw_bone_box;
Batch *drw_bone_box_wire;
Batch *drw_bone_wire_wire;
Batch *drw_bone_point;
Batch *drw_bone_point_wire;
Batch *drw_bone_arrows;
Batch *drw_camera;
Batch *drw_camera_tria;
Batch *drw_camera_focus;
} SHC = {NULL};
void DRW_shape_cache_free(void)
{
BATCH_DISCARD_ALL_SAFE(SHC.drw_single_vertice);
BATCH_DISCARD_ALL_SAFE(SHC.drw_fullscreen_quad);
BATCH_DISCARD_ALL_SAFE(SHC.drw_plain_axes);
BATCH_DISCARD_ALL_SAFE(SHC.drw_single_arrow);
BATCH_DISCARD_ALL_SAFE(SHC.drw_cube);
BATCH_DISCARD_ALL_SAFE(SHC.drw_circle);
BATCH_DISCARD_ALL_SAFE(SHC.drw_square);
BATCH_DISCARD_ALL_SAFE(SHC.drw_line);
BATCH_DISCARD_ALL_SAFE(SHC.drw_line_endpoints);
BATCH_DISCARD_ALL_SAFE(SHC.drw_empty_sphere);
BATCH_DISCARD_ALL_SAFE(SHC.drw_empty_cone);
BATCH_DISCARD_ALL_SAFE(SHC.drw_arrows);
BATCH_DISCARD_ALL_SAFE(SHC.drw_axis_names);
BATCH_DISCARD_ALL_SAFE(SHC.drw_field_wind);
BATCH_DISCARD_ALL_SAFE(SHC.drw_field_force);
BATCH_DISCARD_ALL_SAFE(SHC.drw_field_vortex);
BATCH_DISCARD_ALL_SAFE(SHC.drw_field_tube_limit);
BATCH_DISCARD_ALL_SAFE(SHC.drw_field_cone_limit);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp_sunrays);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp_area);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp_hemi);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp_spot);
BATCH_DISCARD_ALL_SAFE(SHC.drw_lamp_spot_square);
BATCH_DISCARD_ALL_SAFE(SHC.drw_speaker);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_octahedral);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_octahedral_wire);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_box);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_box_wire);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_wire_wire);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_point);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_point_wire);
BATCH_DISCARD_ALL_SAFE(SHC.drw_bone_arrows);
BATCH_DISCARD_ALL_SAFE(SHC.drw_camera);
BATCH_DISCARD_ALL_SAFE(SHC.drw_camera_tria);
BATCH_DISCARD_ALL_SAFE(SHC.drw_camera_focus);
}
/* -------------------------------------------------------------------- */
/** \name Helper functions
* \{ */
static void add_fancy_edge(
VertexBuffer *vbo, unsigned int pos_id, unsigned int n1_id, unsigned int n2_id,
unsigned int *v_idx, const float co1[3], const float co2[3],
const float n1[3], const float n2[3])
{
VertexBuffer_set_attrib(vbo, n1_id, *v_idx, n1);
VertexBuffer_set_attrib(vbo, n2_id, *v_idx, n2);
VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, co1);
VertexBuffer_set_attrib(vbo, n1_id, *v_idx, n1);
VertexBuffer_set_attrib(vbo, n2_id, *v_idx, n2);
VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, co2);
}
static void add_lat_lon_vert(
VertexBuffer *vbo, unsigned int pos_id, unsigned int nor_id,
unsigned int *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);
VertexBuffer_set_attrib(vbo, nor_id, *v_idx, nor);
VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, pos);
}
static VertexBuffer *fill_arrows_vbo(const float scale)
{
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
/* Line */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(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);
VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 0, vtmp1);
VertexBuffer_set_attrib(vbo, pos_id, 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);
VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 2, vtmp1);
VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 3, vtmp2);
v1[arrow_axis] = 0.08f;
mul_v3_v3fl(vtmp1, v1, scale);
mul_v3_v3fl(vtmp2, v2, scale);
VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 4, vtmp1);
VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 5, vtmp2);
/* reset v1 & v2 to zero */
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
}
return vbo;
}
static VertexBuffer *sphere_wire_vbo(const float rad)
{
#define NSEGMENTS 16
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
/* 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], v[3];
cv[0] = p[(i + j) % NSEGMENTS][0];
cv[1] = p[(i + j) % NSEGMENTS][1];
if (axis == 0)
v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
else if (axis == 1)
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
else
v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1];
VertexBuffer_set_attrib(vbo, pos_id, i * 2 + j + (NSEGMENTS * 2 * axis), v);
}
}
}
return vbo;
#undef NSEGMENTS
}
/* Quads */
Batch *DRW_cache_fullscreen_quad_get(void)
{
if (!SHC.drw_fullscreen_quad) {
float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {-1.0f, 1.0f}, { 1.0f, 1.0f}};
float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, { 0.0f, 1.0f}, { 1.0f, 1.0f}};
/* Position Only 2D format */
static VertexFormat format = { 0 };
static unsigned int pos_id, uvs_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
uvs_id = VertexFormat_add_attrib(&format, "uvs", COMP_F32, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 4);
for (int i = 0; i < 4; ++i) {
VertexBuffer_set_attrib(vbo, pos_id, i, pos[i]);
VertexBuffer_set_attrib(vbo, uvs_id, i, uvs[i]);
}
SHC.drw_fullscreen_quad = Batch_create(PRIM_TRIANGLE_STRIP, vbo, NULL);
}
return SHC.drw_fullscreen_quad;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Common
* \{ */
Batch *DRW_cache_cube_get(void)
{
if (!SHC.drw_cube) {
const GLfloat verts[8][3] = {
{-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, -1.0f, -1.0f},
{ 1.0f, -1.0f, 1.0f},
{ 1.0f, 1.0f, -1.0f},
{ 1.0f, 1.0f, 1.0f}
};
const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 24);
for (int i = 0; i < 24; ++i) {
VertexBuffer_set_attrib(vbo, pos_id, i, verts[indices[i]]);
}
SHC.drw_cube = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_cube;
}
Batch *DRW_cache_circle_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_circle) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2);
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v);
}
SHC.drw_circle = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_circle;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_square_get(void)
{
if (!SHC.drw_square) {
float p[4][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}};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 8);
for (int i = 0; i < 4; i++) {
VertexBuffer_set_attrib(vbo, pos_id, i * 2, p[i % 4]);
VertexBuffer_set_attrib(vbo, pos_id, i * 2 + 1, p[(i+1) % 4]);
}
SHC.drw_square = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_square;
}
Batch *DRW_cache_single_line_get(void)
{
/* Z axis line */
if (!SHC.drw_line) {
float v1[3] = {0.0f, 0.0f, 0.0f};
float v2[3] = {0.0f, 0.0f, 1.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 2);
VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
SHC.drw_line = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_line;
}
Batch *DRW_cache_single_line_endpoints_get(void)
{
/* Z axis line */
if (!SHC.drw_line_endpoints) {
float v1[3] = {0.0f, 0.0f, 0.0f};
float v2[3] = {0.0f, 0.0f, 1.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 2);
VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
SHC.drw_line_endpoints = Batch_create(PRIM_POINTS, vbo, NULL);
}
return SHC.drw_line_endpoints;
}
Batch *DRW_cache_screenspace_circle_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_screenspace_circle) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL + 1);
for (int a = 0; a <= CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
VertexBuffer_set_attrib(vbo, pos_id, a, v);
}
SHC.drw_screenspace_circle = Batch_create(PRIM_LINE_STRIP, vbo, NULL);
}
return SHC.drw_screenspace_circle;
#undef CIRCLE_RESOL
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Common Object API
* \{ */
Batch *DRW_cache_object_wire_outline_get(Object *ob)
{
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_wire_outline_get(ob);
/* TODO, should match 'DRW_cache_object_surface_get' */
default:
return NULL;
}
}
Batch *DRW_cache_object_surface_get(Object *ob)
{
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_get(ob);
case OB_CURVE:
return DRW_cache_curve_surface_get(ob);
case OB_SURF:
return DRW_cache_surf_surface_get(ob);
case OB_FONT:
return DRW_cache_text_surface_get(ob);
default:
return NULL;
}
}
Batch **DRW_cache_object_surface_material_get(struct Object *ob)
{
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob);
default:
return NULL;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Empties
* \{ */
Batch *DRW_cache_plain_axes_get(void)
{
if (!SHC.drw_plain_axes) {
int axis;
float v1[3] = {0.0f, 0.0f, 0.0f};
float v2[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 6);
for (axis = 0; axis < 3; axis++) {
v1[axis] = 1.0f;
v2[axis] = -1.0f;
VertexBuffer_set_attrib(vbo, pos_id, axis * 2, v1);
VertexBuffer_set_attrib(vbo, pos_id, axis * 2 + 1, v2);
/* reset v1 & v2 to zero for next axis */
v1[axis] = v2[axis] = 0.0f;
}
SHC.drw_plain_axes = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_plain_axes;
}
Batch *DRW_cache_single_arrow_get(void)
{
if (!SHC.drw_single_arrow) {
float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
/* Square Pyramid */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 12);
v2[0] = 0.035f; v2[1] = 0.035f;
v3[0] = -0.035f; v3[1] = 0.035f;
v2[2] = v3[2] = 0.75f;
for (int sides = 0; sides < 4; sides++) {
if (sides % 2 == 1) {
v2[0] = -v2[0];
v3[1] = -v3[1];
}
else {
v2[1] = -v2[1];
v3[0] = -v3[0];
}
VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 0, v1);
VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 1, v2);
VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 2, v3);
}
SHC.drw_single_arrow = Batch_create(PRIM_TRIANGLES, vbo, NULL);
}
return SHC.drw_single_arrow;
}
Batch *DRW_cache_empty_sphere_get(void)
{
if (!SHC.drw_empty_sphere) {
VertexBuffer *vbo = sphere_wire_vbo(1.0f);
SHC.drw_empty_sphere = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_empty_sphere;
}
Batch *DRW_cache_empty_cone_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_empty_cone) {
/* 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 VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
cv[0] = p[(i) % NSEGMENTS][0];
cv[1] = p[(i) % NSEGMENTS][1];
/* cone sides */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
VertexBuffer_set_attrib(vbo, pos_id, i * 4, v);
v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 1, v);
/* end ring */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 2, v);
cv[0] = p[(i + 1) % NSEGMENTS][0];
cv[1] = p[(i + 1) % NSEGMENTS][1];
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 3, v);
}
SHC.drw_empty_cone = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_empty_cone;
#undef NSEGMENTS
}
Batch *DRW_cache_arrows_get(void)
{
if (!SHC.drw_arrows) {
VertexBuffer *vbo = fill_arrows_vbo(1.0f);
SHC.drw_arrows = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_arrows;
}
Batch *DRW_cache_axis_names_get(void)
{
if (!SHC.drw_axis_names) {
const float size = 0.1f;
float v1[3], v2[3];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
/* Using 3rd component as axis indicator */
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
/* Line */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 14);
/* X */
copy_v3_fl3(v1, -size, size, 0.0f);
copy_v3_fl3(v2, size, -size, 0.0f);
VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
copy_v3_fl3(v1, size, size, 0.0f);
copy_v3_fl3(v2, -size, -size, 0.0f);
VertexBuffer_set_attrib(vbo, pos_id, 2, v1);
VertexBuffer_set_attrib(vbo, pos_id, 3, v2);
/* Y */
copy_v3_fl3(v1, -size + 0.25f * size, size, 1.0f);
copy_v3_fl3(v2, 0.0f, 0.0f, 1.0f);
VertexBuffer_set_attrib(vbo, pos_id, 4, v1);
VertexBuffer_set_attrib(vbo, pos_id, 5, v2);
copy_v3_fl3(v1, size - 0.25f * size, size, 1.0f);
copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f);
VertexBuffer_set_attrib(vbo, pos_id, 6, v1);
VertexBuffer_set_attrib(vbo, pos_id, 7, v2);
/* Z */
copy_v3_fl3(v1, -size, size, 2.0f);
copy_v3_fl3(v2, size, size, 2.0f);
VertexBuffer_set_attrib(vbo, pos_id, 8, v1);
VertexBuffer_set_attrib(vbo, pos_id, 9, v2);
copy_v3_fl3(v1, size, size, 2.0f);
copy_v3_fl3(v2, -size, -size, 2.0f);
VertexBuffer_set_attrib(vbo, pos_id, 10, v1);
VertexBuffer_set_attrib(vbo, pos_id, 11, v2);
copy_v3_fl3(v1, -size, -size, 2.0f);
copy_v3_fl3(v2, size, -size, 2.0f);
VertexBuffer_set_attrib(vbo, pos_id, 12, v1);
VertexBuffer_set_attrib(vbo, pos_id, 13, v2);
SHC.drw_axis_names = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_axis_names;
}
/* Force Field */
Batch *DRW_cache_field_wind_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_wind) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 4);
for (int i = 0; i < 4; i++) {
float z = 0.05f * (float)i;
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
}
}
SHC.drw_field_wind = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_field_wind;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_field_force_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_force) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 3);
for (int i = 0; i < 3; i++) {
float radius = 1.0f + 0.5f * (float)i;
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));
v[2] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2, v);
v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
}
}
SHC.drw_field_force = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_field_force;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_field_vortex_get(void)
{
#define SPIRAL_RESOL 32
if (!SHC.drw_field_vortex) {
float v[3] = {0.0f, 0.0f, 0.0f};
unsigned int v_idx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, SPIRAL_RESOL * 2 + 1);
for (int a = SPIRAL_RESOL; a > -1; a--) {
v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
for (int a = 1; a <= SPIRAL_RESOL; a++) {
v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
SHC.drw_field_vortex = Batch_create(PRIM_LINE_STRIP, vbo, NULL);
}
return SHC.drw_field_vortex;
#undef SPIRAL_RESOL
}
Batch *DRW_cache_field_tube_limit_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_tube_limit) {
float v[3] = {0.0f, 0.0f, 0.0f};
unsigned int v_idx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 + 8);
/* Caps */
for (int i = 0; i < 2; i++) {
float z = (float)i * 2.0f - 1.0f;
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
}
/* Side Edges */
for (int a = 0; a < 4; a++) {
for (int i = 0; i < 2; i++) {
float z = (float)i * 2.0f - 1.0f;
v[0] = sinf((2.0f * M_PI * a) / 4.0f);
v[1] = cosf((2.0f * M_PI * a) / 4.0f);
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
}
SHC.drw_field_tube_limit = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_field_tube_limit;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_field_cone_limit_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_field_cone_limit) {
float v[3] = {0.0f, 0.0f, 0.0f};
unsigned int v_idx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 + 8);
/* Caps */
for (int i = 0; i < 2; i++) {
float z = (float)i * 2.0f - 1.0f;
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
}
/* Side Edges */
for (int a = 0; a < 4; a++) {
for (int i = 0; i < 2; i++) {
float z = (float)i * 2.0f - 1.0f;
v[0] = z * sinf((2.0f * M_PI * a) / 4.0f);
v[1] = z * cosf((2.0f * M_PI * a) / 4.0f);
v[2] = z;
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
}
}
SHC.drw_field_cone_limit = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_field_cone_limit;
#undef CIRCLE_RESOL
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lamps
* \{ */
Batch *DRW_cache_lamp_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_lamp) {
float v[2];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 2);
for (int a = 0; a < NSEGMENTS; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
VertexBuffer_set_attrib(vbo, pos_id, a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v);
}
SHC.drw_lamp = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp;
#undef NSEGMENTS
}
Batch *DRW_cache_lamp_sunrays_get(void)
{
if (!SHC.drw_lamp_sunrays) {
float v[2], v1[2], v2[2];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 16);
for (int a = 0; a < 8; a++) {
v[0] = sinf((2.0f * M_PI * a) / 8.0f);
v[1] = cosf((2.0f * M_PI * a) / 8.0f);
mul_v2_v2fl(v1, v, 1.2f);
mul_v2_v2fl(v2, v, 2.5f);
VertexBuffer_set_attrib(vbo, pos_id, a * 2, v1);
VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v2);
}
SHC.drw_lamp_sunrays = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp_sunrays;
}
Batch *DRW_cache_lamp_area_get(void)
{
if (!SHC.drw_lamp_area) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 8);
v1[0] = v1[1] = 0.5f;
VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
v1[0] = -0.5f;
VertexBuffer_set_attrib(vbo, pos_id, 1, v1);
VertexBuffer_set_attrib(vbo, pos_id, 2, v1);
v1[1] = -0.5f;
VertexBuffer_set_attrib(vbo, pos_id, 3, v1);
VertexBuffer_set_attrib(vbo, pos_id, 4, v1);
v1[0] = 0.5f;
VertexBuffer_set_attrib(vbo, pos_id, 5, v1);
VertexBuffer_set_attrib(vbo, pos_id, 6, v1);
v1[1] = 0.5f;
VertexBuffer_set_attrib(vbo, pos_id, 7, v1);
SHC.drw_lamp_area = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp_area;
}
Batch *DRW_cache_lamp_hemi_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_lamp_hemi) {
float v[3];
int vidx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
/* XZ plane */
for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
v[1] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
v[1] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
}
/* XY plane */
for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[0] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[0] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
}
/* YZ plane full circle */
/* lease v[2] as it is */
const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
}
SHC.drw_lamp_hemi = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp_hemi;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_lamp_spot_get(void)
{
#define NSEGMENTS 32
if (!SHC.drw_lamp_spot) {
/* a single ring of vertices */
float p[NSEGMENTS][2];
float n[NSEGMENTS][3];
float neg[NSEGMENTS][3];
float half_angle = 2 * M_PI / ((float)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);
n[i][0] = cosf(angle - half_angle);
n[i][1] = sinf(angle - half_angle);
n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
normalize_v3(n[i]); /* necessary ? */
negate_v3_v3(neg[i], n[i]);
}
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
cv[0] = p[i % NSEGMENTS][0];
cv[1] = p[i % NSEGMENTS][1];
/* cone sides */
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * 4, v);
v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 1, v);
VertexBuffer_set_attrib(vbo, n1_id, i * 4, n[(i) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 1, n[(i) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n2_id, i * 4, n[(i+1) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 1, n[(i+1) % NSEGMENTS]);
/* end ring */
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 2, v);
cv[0] = p[(i + 1) % NSEGMENTS][0];
cv[1] = p[(i + 1) % NSEGMENTS][1];
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 3, v);
VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 2, n[(i) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 3, n[(i) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 2, neg[(i) % NSEGMENTS]);
VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 3, neg[(i) % NSEGMENTS]);
}
SHC.drw_lamp_spot = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp_spot;
#undef NSEGMENTS
}
Batch *DRW_cache_lamp_spot_square_get(void)
{
if (!SHC.drw_lamp_spot_square) {
float p[5][3] = {{ 0.0f, 0.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}};
unsigned int v_idx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 16);
/* piramid sides */
for (int i = 1; i <= 4; ++i) {
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[0]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[i]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[(i % 4)+1]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[((i+1) % 4)+1]);
}
SHC.drw_lamp_spot_square = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_lamp_spot_square;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Speaker
* \{ */
Batch *DRW_cache_speaker_get(void)
{
if (!SHC.drw_speaker) {
float v[3];
const int segments = 16;
int vidx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(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);
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
for (int i = 1; i < segments; i++) {
float x = cosf(2.f * (float)M_PI * i / segments) * r;
float y = sinf(2.f * (float)M_PI * i / segments) * r;
copy_v3_fl3(v, x, y, z);
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
}
copy_v3_fl3(v, r, 0.0f, z);
VertexBuffer_set_attrib(vbo, pos_id, 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);
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
if (i == 1) {
VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
}
}
}
SHC.drw_speaker = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_speaker;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \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}
};
static const unsigned int 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 unsigned int 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,
};
static const unsigned int 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}
};
/* 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}
};
Batch *DRW_cache_bone_octahedral_get(void)
{
if (!SHC.drw_bone_octahedral) {
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, nor_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 24);
for (int i = 0; i < 8; i++) {
VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
}
SHC.drw_bone_octahedral = Batch_create(PRIM_TRIANGLES, vbo, NULL);
}
return SHC.drw_bone_octahedral;
}
Batch *DRW_cache_bone_octahedral_wire_outline_get(void)
{
if (!SHC.drw_bone_octahedral_wire) {
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 12 * 2);
for (int i = 0; i < 12; i++) {
const float *co1 = bone_octahedral_verts[bone_octahedral_wire[i * 2]];
const float *co2 = bone_octahedral_verts[bone_octahedral_wire[i * 2 + 1]];
const float *n1 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2]];
const float *n2 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2 + 1]];
add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n1, n2);
}
SHC.drw_bone_octahedral_wire = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_bone_octahedral_wire;
}
/* 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 unsigned int 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,
};
/* aligned with bone_octahedral_wire
* Contains adjacent normal index */
static const unsigned int 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,
};
static const unsigned int bone_box_solid_tris[12][3] = {
{0, 1, 2}, /* bottom */
{0, 2, 3},
{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},
};
/* aligned with bone_octahedral_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},
};
Batch *DRW_cache_bone_box_get(void)
{
if (!SHC.drw_bone_box) {
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, nor_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 36);
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 3; j++) {
VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_box_solid_normals[i]);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
}
}
SHC.drw_bone_box = Batch_create(PRIM_TRIANGLES, vbo, NULL);
}
return SHC.drw_bone_box;
}
Batch *DRW_cache_bone_box_wire_outline_get(void)
{
if (!SHC.drw_bone_box_wire) {
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 12 * 2);
for (int i = 0; i < 12; i++) {
const float *co1 = bone_box_verts[bone_box_wire[i * 2]];
const float *co2 = bone_box_verts[bone_box_wire[i * 2 + 1]];
const float *n1 = bone_box_solid_normals[bone_box_wire_adjacent_face[i * 2]];
const float *n2 = bone_box_solid_normals[bone_box_wire_adjacent_face[i * 2 + 1]];
add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n1, n2);
}
SHC.drw_bone_box_wire = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_bone_box_wire;
}
Batch *DRW_cache_bone_wire_wire_outline_get(void)
{
if (!SHC.drw_bone_wire_wire) {
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 2);
const float co1[3] = {0.0f, 0.0f, 0.0f};
const float co2[3] = {0.0f, 1.0f, 0.0f};
const float n[3] = {1.0f, 0.0f, 0.0f};
add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n, n);
SHC.drw_bone_wire_wire = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_bone_wire_wire;
}
Batch *DRW_cache_bone_point_get(void)
{
if (!SHC.drw_bone_point) {
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;
unsigned int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id, nor_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(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, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon);
add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon);
}
if (j != 0) { /* Pole */
add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon + lon_inc);
add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon);
}
}
}
SHC.drw_bone_point = Batch_create(PRIM_TRIANGLES, vbo, NULL);
}
return SHC.drw_bone_point;
}
Batch *DRW_cache_bone_point_wire_outline_get(void)
{
if (!SHC.drw_bone_point_wire) {
VertexBuffer *vbo = sphere_wire_vbo(0.05f);
SHC.drw_bone_point_wire = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_bone_point_wire;
}
Batch *DRW_cache_bone_arrows_get(void)
{
if (!SHC.drw_bone_arrows) {
VertexBuffer *vbo = fill_arrows_vbo(0.25f);
SHC.drw_bone_arrows = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_bone_arrows;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Camera
* \{ */
Batch *DRW_cache_camera_get(void)
{
if (!SHC.drw_camera) {
float v0 = 0.0f; /* Center point */
float v1 = 1.0f; /* + X + Y */
float v2 = 2.0f; /* + X - Y */
float v3 = 3.0f; /* - X - Y */
float v4 = 4.0f; /* - X + Y */
float v5 = 5.0f; /* tria + X */
float v6 = 6.0f; /* tria - X */
float v7 = 7.0f; /* tria + Y */
int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
/* use x coordinate to identify the vertex
* the vertex shader take care to place it
* appropriatelly */
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 1, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 22);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
/* camera frame */
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
/* tria */
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
SHC.drw_camera = Batch_create(PRIM_LINES, vbo, NULL);
}
return SHC.drw_camera;
}
Batch *DRW_cache_camera_tria_get(void)
{
if (!SHC.drw_camera_tria) {
float v5 = 5.0f; /* tria + X */
float v6 = 6.0f; /* tria - X */
float v7 = 7.0f; /* tria + Y */
int v_idx = 0;
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
/* use x coordinate to identify the vertex
* the vertex shader take care to place it
* appropriatelly */
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 1, KEEP_FLOAT);
}
/* Vertices */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 6);
/* tria */
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
SHC.drw_camera_tria = Batch_create(PRIM_TRIANGLES, vbo, NULL);
}
return SHC.drw_camera_tria;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Object Mode Helpers
* \{ */
/* Object Center */
Batch *DRW_cache_single_vert_get(void)
{
if (!SHC.drw_single_vertice) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 1);
VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
SHC.drw_single_vertice = Batch_create(PRIM_POINTS, vbo, NULL);
}
return SHC.drw_single_vertice;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Meshes
* \{ */
Batch *DRW_cache_mesh_surface_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_all_triangles(me);
}
void DRW_cache_mesh_wire_overlay_get(
Object *ob,
Batch **r_tris, Batch **r_ledges, Batch **r_lverts)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
*r_tris = DRW_mesh_batch_cache_get_overlay_triangles(me);
*r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges(me);
*r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
}
Batch *DRW_cache_face_centers_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_overlay_facedots(me);
}
Batch *DRW_cache_mesh_wire_outline_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_fancy_edges(me);
}
Batch *DRW_cache_mesh_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_triangles_with_normals(me);
}
Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me, ob->actdef - 1);
}
/* Return list of batches */
Batch **DRW_cache_mesh_surface_shaded_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_surface_shaded(me);
}
Batch *DRW_cache_mesh_surface_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_points_with_normals(me);
}
Batch *DRW_cache_mesh_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_all_edges(me);
}
Batch *DRW_cache_mesh_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_all_verts(me);
}
Batch *DRW_cache_mesh_edges_weight_overlay_get(Object *ob, bool use_wire, bool use_sel)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_weight_overlay_edges(me, use_wire, use_sel);
}
Batch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_weight_overlay_faces(me);
}
Batch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
return DRW_mesh_batch_cache_get_weight_overlay_verts(me);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Curve
* \{ */
Batch *DRW_cache_curve_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
}
Batch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_normal_edge(cu, ob->curve_cache, normal_size);
}
Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_overlay_edges(cu);
}
Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_overlay_verts(cu);
}
Batch *DRW_cache_curve_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Font
* \{ */
Batch *DRW_cache_text_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
}
Batch *DRW_cache_text_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
Batch *DRW_cache_text_cursor_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_overlay_cursor(cu);
}
Batch *DRW_cache_text_select_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_overlay_select(cu);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Surface
* \{ */
Batch *DRW_cache_surf_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lattice
* \{ */
Batch *DRW_cache_lattice_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_LATTICE);
struct Lattice *lt = ob->data;
return DRW_lattice_batch_cache_get_all_verts(lt);
}
Batch *DRW_cache_lattice_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_LATTICE);
struct Lattice *lt = ob->data;
return DRW_lattice_batch_cache_get_all_edges(lt);
}
Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_LATTICE);
struct Lattice *lt = ob->data;
return DRW_lattice_batch_cache_get_overlay_verts(lt);
}
/** \} */