OpenGL: Object bound drawing.

This commit is contained in:
Clément Foucault 2017-03-06 20:55:58 +01:00
parent 517db46b34
commit 583373f049
8 changed files with 159 additions and 56 deletions

View File

@ -112,7 +112,8 @@ void imm_cpack(unsigned int x);
* \param slices Specifies the number of subdivisions around the z axis.
* \param stacks Specifies the number of subdivisions along the z axis.
*/
void imm_cylinder(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks);
void imm_cylinder_nor(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks);
void imm_cylinder_wire(unsigned int pos, float base, float top, float height, int slices, int stacks);
/**
* Returns a float value as obtained by glGetFloatv.

View File

@ -164,7 +164,7 @@ void imm_cpack(unsigned int x)
(((x) >> 16) & 0xFF));
}
void imm_cylinder(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
void imm_cylinder_nor(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
{
immBegin(GL_TRIANGLES, 6 * slices * stacks);
for (int i = 0; i < slices; ++i) {
@ -215,6 +215,43 @@ void imm_cylinder(unsigned int pos, unsigned int nor, float base, float top, flo
immEnd();
}
void imm_cylinder_wire(unsigned int pos, float base, float top, float height, int slices, int stacks)
{
immBegin(GL_LINES, 6 * slices * stacks);
for (int i = 0; i < slices; ++i) {
const float angle1 = 2 * M_PI * ((float)i / (float)slices);
const float angle2 = 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.f - fac1) + top * fac1;
float r2 = base * (1.f - fac2) + top * fac2;
float h1 = height * ((float)j / (float)stacks);
float h2 = height * ((float)(j+1) / (float)stacks);
float v1[3] = {r1 * cos2, r1 * sin2, h1};
float v2[3] = {r2 * cos2, r2 * sin2, h2};
float v3[3] = {r2 * cos1, r2 * sin1, h2};
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();
}
float glaGetOneFloat(int param)
{
GLfloat v;

View File

@ -1131,7 +1131,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
immUniform3fv("light", light_vec);
gpuTranslate3f(0.0f, 0.0f, head);
imm_cylinder(pos, nor, size2, size1, length - head - tail, 16, 1);
imm_cylinder_nor(pos, nor, size2, size1, length - head - tail, 16, 1);
immUnbindProgram();

View File

@ -110,9 +110,7 @@
#include "view3d_intern.h" /* bad level include */
/* prototypes */
#ifdef WITH_GAMEENGINE
static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos);
#endif
/* Workaround for sequencer scene render mode.
*
@ -4251,7 +4249,7 @@ static void draw_mesh_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v
if (dt == OB_BOUNDBOX) {
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else if ((no_faces && no_edges) ||
((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
@ -4672,7 +4670,7 @@ static void draw_mesh_fancy_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3
if (dt == OB_BOUNDBOX) {
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else if ((no_faces && no_edges) ||
((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
@ -7773,7 +7771,6 @@ static void draw_box(const float vec[8][3], bool solid)
glDisableClientState(GL_VERTEX_ARRAY);
}
#ifdef WITH_GAMEENGINE
static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
{
static const GLubyte quad_indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2};
@ -7797,14 +7794,13 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
}
immEnd();
}
#endif
static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4])
{
float size[3], cent[3];
GLUquadricObj *qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
Batch *sphere = Batch_get_sphere_wire(0);
Batch_set_builtin_program(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
if (ob_wire_col) Batch_Uniform4f(sphere, "color", ob_wire_col[0]/255.0f, ob_wire_col[1]/255.0f, ob_wire_col[2]/255.0f, 1.0f);
BKE_boundbox_calc_size_aabb(bb, size);
@ -7815,40 +7811,53 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
BKE_boundbox_calc_center_aabb(bb, cent);
}
glPushMatrix();
gpuMatrixBegin3D_legacy();
gpuPushMatrix();
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
if (type == OB_BOUND_SPHERE) {
float scale = MAX3(size[0], size[1], size[2]);
glTranslate3fv(cent);
glScalef(scale, scale, scale);
gluSphere(qobj, 1.0, 8, 5);
gpuTranslate3fv(cent);
gpuRotateAxis(90, 'X');
gpuScaleUniform(scale);
Batch_draw(sphere);
}
else if (type == OB_BOUND_CYLINDER) {
float radius = size[0] > size[1] ? size[0] : size[1];
glTranslatef(cent[0], cent[1], cent[2] - size[2]);
glScalef(radius, radius, 2.0f * size[2]);
gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
gpuScale3f(radius, radius, 2.0f * size[2]);
imm_cylinder_wire(pos, 1.0f, 1.0f, 1.0f, 8, 1);
}
else if (type == OB_BOUND_CONE) {
float radius = size[0] > size[1] ? size[0] : size[1];
glTranslatef(cent[0], cent[1], cent[2] - size[2]);
glScalef(radius, radius, 2.0f * size[2]);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
gpuScale3f(radius, radius, 2.0f * size[2]);
imm_cylinder_wire(pos, 1.0f, 0.0f, 1.0f, 8, 1);
}
else if (type == OB_BOUND_CAPSULE) {
float radius = size[0] > size[1] ? size[0] : size[1];
float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
gluCylinder(qobj, radius, radius, length, 8, 1);
gluSphere(qobj, radius, 8, 4);
glTranslatef(0.0, 0.0, length);
gluSphere(qobj, radius, 8, 4);
gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f);
imm_cylinder_wire(pos, radius, radius, length, 8, 1);
gpuRotateAxis(90, 'X');
gpuScaleUniform(radius);
Batch_draw(sphere);
gpuTranslate3f(0.0f, length / radius, 0.0f);
Batch_draw(sphere);
}
glPopMatrix();
gluDeleteQuadric(qobj);
gpuPopMatrix();
gpuMatrixEnd();
immUnbindProgram();
}
void draw_bounding_volume(Object *ob, char type)
void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4])
{
BoundBox bb_local;
BoundBox *bb = NULL;
@ -7878,12 +7887,16 @@ void draw_bounding_volume(Object *ob, char type)
if (bb == NULL)
return;
if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */
if (type == OB_BOUND_BOX) {
float vec[8][3], size[3];
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
BKE_boundbox_calc_size_aabb(bb, size);
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
@ -7893,18 +7906,28 @@ void draw_bounding_volume(Object *ob, char type)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
draw_box(vec, false);
imm_draw_box(vec, false, pos);
immUnbindProgram();
}
else {
draw_bb_quadric(bb, type, true);
imm_draw_bb(bb, type, true, ob_wire_col);
}
}
else {
if (type == OB_BOUND_BOX)
draw_box(bb->vec, false);
if (type == OB_BOUND_BOX) {
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
imm_draw_box(bb->vec, false, pos);
immUnbindProgram();
}
else
draw_bb_quadric(bb, type, false);
imm_draw_bb(bb, type, false, ob_wire_col);
}
}
static void drawtexspace(Object *ob)
@ -8190,7 +8213,7 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob)
v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
}
void draw_rigidbody_shape(Object *ob)
void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4])
{
BoundBox *bb = NULL;
float size[3], vec[8][3];
@ -8216,16 +8239,16 @@ void draw_rigidbody_shape(Object *ob)
draw_box(vec, false);
break;
case RB_SHAPE_SPHERE:
draw_bb_quadric(bb, OB_BOUND_SPHERE, true);
imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col);
break;
case RB_SHAPE_CONE:
draw_bb_quadric(bb, OB_BOUND_CONE, true);
imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col);
break;
case RB_SHAPE_CYLINDER:
draw_bb_quadric(bb, OB_BOUND_CYLINDER, true);
imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col);
break;
case RB_SHAPE_CAPSULE:
draw_bb_quadric(bb, OB_BOUND_CAPSULE, true);
imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col);
break;
}
}
@ -8455,7 +8478,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
@ -8476,7 +8499,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
@ -8494,7 +8517,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else
@ -8533,7 +8556,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
#ifdef SEQUENCER_DAG_WORKAROUND
@ -8549,7 +8572,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE)))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
unsigned char arm_col[4];
@ -8742,12 +8765,12 @@ afterdraw:
if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) {
if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) {
setlinestyle(2);
draw_bounding_volume(ob, ob->collision_boundtype);
draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col);
setlinestyle(0);
}
}
if (ob->rigidbody_object) {
draw_rigidbody_shape(ob);
draw_rigidbody_shape(ob, ob_wire_col);
}
/* draw extra: after normal draw because of makeDispList */
@ -8763,7 +8786,7 @@ afterdraw:
}
}
if (dtx & OB_DRAWBOUNDOX) {
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
if (dtx & OB_TEXSPACE) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@ -8883,6 +8906,7 @@ afterdraw:
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor3ubv(ob_wire_col);
/* draw hook center and offset line */
if (ob != scene->obedit)

View File

@ -1799,7 +1799,7 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
case OB_SURF:
case OB_MBALL:
if (is_boundingbox) {
draw_bounding_volume(ob, ob->boundtype);
draw_bounding_volume(ob, ob->boundtype, color);
}
break;
case OB_EMPTY:
@ -1826,7 +1826,7 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
}
if (ob->rigidbody_object) {
draw_rigidbody_shape(ob);
draw_rigidbody_shape(ob, color);
}
ED_view3d_clear_mats_rv3d(rv3d);

View File

@ -159,8 +159,8 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
const short dflag, const unsigned char ob_wire_col[4]);
void drawspeaker(const unsigned char ob_wire_col[3]);
void draw_bounding_volume(struct Object *ob, char type);
void draw_rigidbody_shape(struct Object *ob);
void draw_bounding_volume(struct Object *ob, char type, const unsigned char ob_wire_col[4]);
void draw_rigidbody_shape(struct Object *ob, const unsigned char ob_wire_col[4]);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3],

View File

@ -38,6 +38,7 @@ void Batch_set_builtin_program(Batch*, GPUBuiltinShader);
/* Replacement for gluSphere */
Batch *Batch_get_sphere(int lod);
Batch *Batch_get_sphere_wire(int lod);
void gpu_batch_init(void);
void gpu_batch_exit(void);

View File

@ -40,6 +40,7 @@ void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id)
static Batch *sphere_high = NULL;
static Batch *sphere_med = NULL;
static Batch *sphere_low = NULL;
static Batch *sphere_wire_low = NULL;
static VertexBuffer *vbo;
static VertexFormat format = {0};
@ -94,6 +95,38 @@ static Batch *batch_sphere(int lat_res, int lon_res)
return Batch_create(GL_TRIANGLES, vbo, NULL);
}
static Batch *batch_sphere_wire(int lat_res, int lon_res)
{
const float lon_inc = 2 * M_PI / lon_res;
const float lat_inc = M_PI / lat_res;
float lon, lat;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
}
vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, (lat_res * lon_res * 2) + ((lat_res-1) * lon_res * 2));
vert = 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) {
batch_sphere_lat_lon_vert(lat+lat_inc, lon);
batch_sphere_lat_lon_vert(lat, lon);
if (j != lat_res - 1) { /* Pole */
batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc);
batch_sphere_lat_lon_vert(lat+lat_inc, lon);
}
}
}
return Batch_create(GL_LINES, vbo, NULL);
}
Batch *Batch_get_sphere(int lod)
{
BLI_assert(lod >= 0 && lod <= 2);
@ -106,12 +139,19 @@ Batch *Batch_get_sphere(int lod)
return sphere_high;
}
Batch *Batch_get_sphere_wire(int UNUSED(lod))
{
return sphere_wire_low;
}
void gpu_batch_init(void)
{
/* Hard coded resolution */
sphere_low = batch_sphere(8, 16);
sphere_med = batch_sphere(16, 10);
sphere_high = batch_sphere(32, 24);
sphere_wire_low = batch_sphere_wire(6, 8);
}
void gpu_batch_exit(void)