This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/gpu/intern/gpu_immediate_util.c
Jason Fielder 4527dd1ce4 Metal: MTLMemoryManager implementation includes functions which manage allocation of MTLBuffer resources.
The memory manager includes both a GPUContext-local manager which allocates per-context resources such as Circular Scratch Buffers for temporary data such as uniform updates and resource staging, and a GPUContext-global memory manager which features a pooled memory allocator for efficient re-use of resources, to reduce CPU-overhead of frequent memory allocations.

These Memory Managers act as a simple interface for use by other Metal backend modules and to coordinate the lifetime of buffers, to ensure that GPU-resident resources are correctly tracked and freed when no longer in use.

Note: This also contains dependent DIFF changes from D15027, though these will be removed once D15027 lands.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D15277
2022-07-01 10:31:57 +02:00

705 lines
23 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*
* GPU immediate mode drawing utilities
*/
#include <stdio.h>
#include <string.h>
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "GPU_immediate.h"
#include "UI_resources.h"
static const float cube_coords[8][3] = {
{-1, -1, -1},
{-1, -1, +1},
{-1, +1, -1},
{-1, +1, +1},
{+1, -1, -1},
{+1, -1, +1},
{+1, +1, -1},
{+1, +1, +1},
};
static const int cube_quad_index[6][4] = {
{0, 1, 3, 2},
{0, 2, 6, 4},
{0, 4, 5, 1},
{1, 5, 7, 3},
{2, 3, 7, 6},
{4, 6, 7, 5},
};
static const int cube_line_index[12][2] = {
{0, 1},
{0, 2},
{0, 4},
{1, 3},
{1, 5},
{2, 3},
{2, 6},
{3, 7},
{4, 5},
{4, 6},
{5, 7},
{6, 7},
};
void immRectf(uint pos, float x1, float y1, float x2, float y2)
{
immBegin(GPU_PRIM_TRI_FAN, 4);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y1);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x1, y2);
immEnd();
}
void immRecti(uint pos, int x1, int y1, int x2, int y2)
{
immBegin(GPU_PRIM_TRI_FAN, 4);
immVertex2i(pos, x1, y1);
immVertex2i(pos, x2, y1);
immVertex2i(pos, x2, y2);
immVertex2i(pos, x1, y2);
immEnd();
}
void immRectf_fast(uint pos, float x1, float y1, float x2, float y2)
{
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y1);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x1, y2);
}
void immRectf_fast_with_color(
uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4])
{
immAttr4fv(col, color);
immVertex2f(pos, x1, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y2);
immAttr4fv(col, color);
immVertex2f(pos, x1, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y2);
immAttr4fv(col, color);
immVertex2f(pos, x1, y2);
}
void immRecti_fast_with_color(
uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4])
{
immAttr4fv(col, color);
immVertex2i(pos, x1, y1);
immAttr4fv(col, color);
immVertex2i(pos, x2, y1);
immAttr4fv(col, color);
immVertex2i(pos, x2, y2);
immAttr4fv(col, color);
immVertex2i(pos, x1, y1);
immAttr4fv(col, color);
immVertex2i(pos, x2, y2);
immAttr4fv(col, color);
immVertex2i(pos, x1, y2);
}
#if 0 /* more complete version in case we want that */
void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4])
{
GPUVertFormat *format = immVertexFormat();
uint pos = add_attr(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
immRecti(pos, x1, y1, x2, y2);
immUnbindProgram();
}
#endif
void imm_cpack(uint x)
{
immUniformColor3ub(((x)&0xFF), (((x) >> 8) & 0xFF), (((x) >> 16) & 0xFF));
}
static void imm_draw_circle(GPUPrimType prim_type,
const uint shdr_pos,
float x,
float y,
float radius_x,
float radius_y,
int nsegments)
{
if (prim_type == GPU_PRIM_LINE_LOOP) {
/* NOTE(Metal/AMD): For small primitives, line list more efficient than line strip.. */
immBegin(GPU_PRIM_LINES, nsegments * 2);
immVertex2f(shdr_pos, x + (radius_x * cosf(0.0f)), y + (radius_y * sinf(0.0f)));
for (int i = 1; i < nsegments; i++) {
const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle)));
immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle)));
}
immVertex2f(shdr_pos, x + (radius_x * cosf(0.0f)), y + (radius_y * sinf(0.0f)));
immEnd();
}
else {
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle)));
}
immEnd();
}
}
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius, radius, nsegments);
}
void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, radius, radius, nsegments);
}
void imm_draw_circle_wire_aspect_2d(
uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
void imm_draw_circle_fill_aspect_2d(
uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
static void imm_draw_circle_partial(GPUPrimType prim_type,
uint pos,
float x,
float y,
float radius,
int nsegments,
float start,
float sweep)
{
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2;
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
const float angle_sin = sinf(angle);
const float angle_cos = cosf(angle);
immVertex2f(pos, x + radius * angle_cos, y + radius * angle_sin);
}
immEnd();
}
static void imm_draw_circle_partial_3d(GPUPrimType prim_type,
uint pos,
float x,
float y,
float z,
float rad,
int nsegments,
float start,
float sweep)
{
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2);
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
const float angle_sin = sinf(angle);
const float angle_cos = cosf(angle);
immVertex3f(pos, x + rad * angle_cos, y + rad * angle_sin, z);
}
immEnd();
}
void imm_draw_circle_partial_wire_2d(
uint pos, float x, float y, float radius, int nsegments, float start, float sweep)
{
imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, radius, nsegments, start, sweep);
}
void imm_draw_circle_partial_wire_3d(
uint pos, float x, float y, float z, float rad, int nsegments, float start, float sweep)
{
imm_draw_circle_partial_3d(GPU_PRIM_LINE_STRIP, pos, x, y, z, rad, nsegments, start, sweep);
}
static void imm_draw_disk_partial(GPUPrimType prim_type,
uint pos,
float x,
float y,
float rad_inner,
float rad_outer,
int nsegments,
float start,
float sweep)
{
/* to avoid artifacts */
const float max_angle = 3 * 360;
CLAMP(sweep, -max_angle, max_angle);
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2;
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments * 2);
for (int i = 0; i < nsegments; i++) {
const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
const float angle_sin = sinf(angle);
const float angle_cos = cosf(angle);
immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin);
immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin);
}
immEnd();
}
static void imm_draw_disk_partial_3d(GPUPrimType prim_type,
uint pos,
float x,
float y,
float z,
float rad_inner,
float rad_outer,
int nsegments,
float start,
float sweep)
{
/* to avoid artifacts */
const float max_angle = 3 * 360;
CLAMP(sweep, -max_angle, max_angle);
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2;
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments * 2);
for (int i = 0; i < nsegments; i++) {
const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
const float angle_sin = sinf(angle);
const float angle_cos = cosf(angle);
immVertex3f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin, z);
immVertex3f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin, z);
}
immEnd();
}
void imm_draw_disk_partial_fill_2d(uint pos,
float x,
float y,
float rad_inner,
float rad_outer,
int nsegments,
float start,
float sweep)
{
imm_draw_disk_partial(
GPU_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep);
}
void imm_draw_disk_partial_fill_3d(uint pos,
float x,
float y,
float z,
float rad_inner,
float rad_outer,
int nsegments,
float start,
float sweep)
{
imm_draw_disk_partial_3d(
GPU_PRIM_TRI_STRIP, pos, x, y, z, rad_inner, rad_outer, nsegments, start, sweep);
}
static void imm_draw_circle_3D(
GPUPrimType prim_type, uint pos, float x, float y, float radius, int nsegments)
{
if (prim_type == GPU_PRIM_LINE_LOOP) {
/* NOTE(Metal/AMD): For small primitives, line list more efficient than line strip. */
immBegin(GPU_PRIM_LINES, nsegments * 2);
const float angle = (float)(2 * M_PI) / (float)nsegments;
float xprev = cosf(-angle) * radius;
float yprev = sinf(-angle) * radius;
const float alpha = 2.0f * cosf(angle);
float xr = radius;
float yr = 0;
for (int i = 0; i < nsegments; i++) {
immVertex3f(pos, x + xr, y + yr, 0.0f);
if (i) {
immVertex3f(pos, x + xr, y + yr, 0.0f);
}
const float xnext = alpha * xr - xprev;
const float ynext = alpha * yr - yprev;
xprev = xr;
yprev = yr;
xr = xnext;
yr = ynext;
}
immVertex3f(pos, x + radius, y, 0.0f);
immEnd();
}
else {
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f);
}
immEnd();
}
}
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, radius, nsegments);
}
void imm_draw_circle_dashed_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_LINES, pos, x, y, radius, nsegments / 2);
}
void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, radius, nsegments);
}
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
{
/* NOTE(Metal/AMD): For small primitives, line list more efficient than line-strip. */
immBegin(GPU_PRIM_LINES, 8);
immVertex2f(pos, x1, y1);
immVertex2f(pos, x1, y2);
immVertex2f(pos, x1, y2);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x2, y2);
immVertex2f(pos, x2, y1);
immVertex2f(pos, x2, y1);
immVertex2f(pos, x1, y1);
immEnd();
}
void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2)
{
/* use this version when GPUVertFormat has a vec3 position */
/* NOTE(Metal/AMD): For small primitives, line list more efficient than line-strip. */
immBegin(GPU_PRIM_LINES, 8);
immVertex3f(pos, x1, y1, 0.0f);
immVertex3f(pos, x1, y2, 0.0f);
immVertex3f(pos, x1, y2, 0.0f);
immVertex3f(pos, x2, y2, 0.0f);
immVertex3f(pos, x2, y2, 0.0f);
immVertex3f(pos, x2, y1, 0.0f);
immVertex3f(pos, x2, y1, 0.0f);
immVertex3f(pos, x1, y1, 0.0f);
immEnd();
}
void imm_draw_box_checker_2d_ex(float x1,
float y1,
float x2,
float y2,
const float color_primary[4],
const float color_secondary[4],
int checker_size)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
immUniform4fv("color1", color_primary);
immUniform4fv("color2", color_secondary);
immUniform1i("size", checker_size);
immRectf(pos, x1, y1, x2, y2);
immUnbindProgram();
}
void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
{
float checker_primary[4];
float checker_secondary[4];
UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary);
UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary);
int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE);
imm_draw_box_checker_2d_ex(x1, y1, x2, y2, checker_primary, checker_secondary, checker_size);
}
void imm_draw_cube_fill_3d(uint pos, const float center[3], const float aspect[3])
{
float coords[ARRAY_SIZE(cube_coords)][3];
for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
}
immBegin(GPU_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) {
immVertex3fv(pos, coords[cube_quad_index[i][0]]);
immVertex3fv(pos, coords[cube_quad_index[i][1]]);
immVertex3fv(pos, coords[cube_quad_index[i][2]]);
immVertex3fv(pos, coords[cube_quad_index[i][0]]);
immVertex3fv(pos, coords[cube_quad_index[i][2]]);
immVertex3fv(pos, coords[cube_quad_index[i][3]]);
}
immEnd();
}
void imm_draw_cube_wire_3d(uint pos, const float center[3], const float aspect[3])
{
float coords[ARRAY_SIZE(cube_coords)][3];
for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
}
immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
immVertex3fv(pos, coords[cube_line_index[i][0]]);
immVertex3fv(pos, coords[cube_line_index[i][1]]);
}
immEnd();
}
void imm_draw_cube_corners_3d(uint pos,
const float center[3],
const float aspect[3],
const float factor)
{
float coords[ARRAY_SIZE(cube_coords)][3];
for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
}
immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 4);
for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
float vec[3], co[3];
sub_v3_v3v3(vec, coords[cube_line_index[i][1]], coords[cube_line_index[i][0]]);
mul_v3_fl(vec, factor);
copy_v3_v3(co, coords[cube_line_index[i][0]]);
immVertex3fv(pos, co);
add_v3_v3(co, vec);
immVertex3fv(pos, co);
copy_v3_v3(co, coords[cube_line_index[i][1]]);
immVertex3fv(pos, co);
sub_v3_v3(co, vec);
immVertex3fv(pos, co);
}
immEnd();
}
void imm_draw_cylinder_fill_normal_3d(
uint pos, uint nor, float base, float top, float height, int slices, int stacks)
{
immBegin(GPU_PRIM_TRIS, 6 * slices * stacks);
for (int i = 0; i < slices; i++) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
const float cos1 = cosf(angle1);
const float sin1 = sinf(angle1);
const float cos2 = cosf(angle2);
const float sin2 = sinf(angle2);
for (int j = 0; j < stacks; j++) {
float fac1 = (float)j / (float)stacks;
float fac2 = (float)(j + 1) / (float)stacks;
float r1 = base * (1.0f - fac1) + top * fac1;
float r2 = base * (1.0f - fac2) + top * fac2;
float h1 = height * ((float)j / (float)stacks);
float h2 = height * ((float)(j + 1) / (float)stacks);
const float v1[3] = {r1 * cos2, r1 * sin2, h1};
const float v2[3] = {r2 * cos2, r2 * sin2, h2};
const float v3[3] = {r2 * cos1, r2 * sin1, h2};
const float v4[3] = {r1 * cos1, r1 * sin1, h1};
float n1[3], n2[3];
/* calc normals */
sub_v3_v3v3(n1, v2, v1);
normalize_v3(n1);
n1[0] = cos1;
n1[1] = sin1;
n1[2] = 1 - n1[2];
sub_v3_v3v3(n2, v3, v4);
normalize_v3(n2);
n2[0] = cos2;
n2[1] = sin2;
n2[2] = 1 - n2[2];
/* first tri */
immAttr3fv(nor, n2);
immVertex3fv(pos, v1);
immVertex3fv(pos, v2);
immAttr3fv(nor, n1);
immVertex3fv(pos, v3);
/* second tri */
immVertex3fv(pos, v3);
immVertex3fv(pos, v4);
immAttr3fv(nor, n2);
immVertex3fv(pos, v1);
}
}
immEnd();
}
void imm_draw_cylinder_wire_3d(
uint pos, float base, float top, float height, int slices, int stacks)
{
immBegin(GPU_PRIM_LINES, 6 * slices * stacks);
for (int i = 0; i < slices; i++) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
const float cos1 = cosf(angle1);
const float sin1 = sinf(angle1);
const float cos2 = cosf(angle2);
const float sin2 = sinf(angle2);
for (int j = 0; j < stacks; j++) {
float fac1 = (float)j / (float)stacks;
float fac2 = (float)(j + 1) / (float)stacks;
float r1 = base * (1.0f - fac1) + top * fac1;
float r2 = base * (1.0f - fac2) + top * fac2;
float h1 = height * ((float)j / (float)stacks);
float h2 = height * ((float)(j + 1) / (float)stacks);
const float v1[3] = {r1 * cos2, r1 * sin2, h1};
const float v2[3] = {r2 * cos2, r2 * sin2, h2};
const float v3[3] = {r2 * cos1, r2 * sin1, h2};
const float v4[3] = {r1 * cos1, r1 * sin1, h1};
immVertex3fv(pos, v1);
immVertex3fv(pos, v2);
immVertex3fv(pos, v2);
immVertex3fv(pos, v3);
immVertex3fv(pos, v1);
immVertex3fv(pos, v4);
}
}
immEnd();
}
void imm_draw_cylinder_fill_3d(
uint pos, float base, float top, float height, int slices, int stacks)
{
immBegin(GPU_PRIM_TRIS, 6 * slices * stacks);
for (int i = 0; i < slices; i++) {
const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
const float cos1 = cosf(angle1);
const float sin1 = sinf(angle1);
const float cos2 = cosf(angle2);
const float sin2 = sinf(angle2);
for (int j = 0; j < stacks; j++) {
float fac1 = (float)j / (float)stacks;
float fac2 = (float)(j + 1) / (float)stacks;
float r1 = base * (1.0f - fac1) + top * fac1;
float r2 = base * (1.0f - fac2) + top * fac2;
float h1 = height * ((float)j / (float)stacks);
float h2 = height * ((float)(j + 1) / (float)stacks);
const float v1[3] = {r1 * cos2, r1 * sin2, h1};
const float v2[3] = {r2 * cos2, r2 * sin2, h2};
const float v3[3] = {r2 * cos1, r2 * sin1, h2};
const float v4[3] = {r1 * cos1, r1 * sin1, h1};
/* first tri */
immVertex3fv(pos, v1);
immVertex3fv(pos, v2);
immVertex3fv(pos, v3);
/* second tri */
immVertex3fv(pos, v3);
immVertex3fv(pos, v4);
immVertex3fv(pos, v1);
}
}
immEnd();
}
/* Circle Drawing - Tables for Optimized Drawing Speed */
#define CIRCLE_RESOL 32
static void circball_array_fill(const float verts[CIRCLE_RESOL][3],
const float cent[3],
const float radius,
const float tmat[4][4])
{
/* 32 values of sin function (still same result!) */
const float sinval[CIRCLE_RESOL] = {
0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213,
0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196,
0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573,
-0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278,
-0.57126821, -0.39435585, -0.20129852, 0.00000000,
};
/* 32 values of cos function (still same result!) */
const float cosval[CIRCLE_RESOL] = {
1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525,
0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661,
-0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598,
-0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691,
0.82076344, 0.91895781, 0.97952994, 1.00000000,
};
float vx[3], vy[3];
float *viter = (float *)verts;
mul_v3_v3fl(vx, tmat[0], radius);
mul_v3_v3fl(vy, tmat[1], radius);
for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
}
}
void imm_drawcircball(const float cent[3], float radius, const float tmat[4][4], uint pos)
{
float verts[CIRCLE_RESOL][3];
circball_array_fill(verts, cent, radius, tmat);
immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
for (int i = 0; i < CIRCLE_RESOL; i++) {
immVertex3fv(pos, verts[i]);
}
immEnd();
}