Curve: draw curve/surface/text geometry

Note that displists will be removed, but this wont be hard to replace.

Signed-off-by: Campbell Barton <ideasman42@gmail.com>
This commit is contained in:
Campbell Barton
2017-04-21 02:18:14 +10:00
parent 9d1421c069
commit 677aa36632
12 changed files with 363 additions and 21 deletions

View File

@@ -37,4 +37,6 @@ struct Batch *BKE_curve_batch_cache_get_normal_edge(
struct Batch *BKE_curve_batch_cache_get_overlay_edges(struct Curve *cu);
struct Batch *BKE_curve_batch_cache_get_overlay_verts(struct Curve *cu);
struct Batch *BKE_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache);
#endif /* __BKE_CURVE_RENDER_H__ */

View File

@@ -0,0 +1,33 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BKE_DISPLIST_RENDER_H__
#define __BKE_DISPLIST_RENDER_H__
/** \file BKE_displist_render.h
* \ingroup bke
*/
struct Batch;
struct ListBase;
struct VertexBuffer;
struct Batch *BLI_displist_batch_calc_surface(struct ListBase *lb);
#endif /* __BKE_DISPLIST_RENDER_H__ */

View File

@@ -100,6 +100,7 @@ set(SRC
intern/deform.c
intern/depsgraph.c
intern/displist.c
intern/displist_render.c
intern/dynamicpaint.c
intern/editderivedmesh.c
intern/editmesh.c
@@ -233,6 +234,7 @@ set(SRC
BKE_deform.h
BKE_depsgraph.h
BKE_displist.h
BKE_displist_render.h
BKE_dynamicpaint.h
BKE_editmesh.h
BKE_editmesh_bvh.h

View File

@@ -37,6 +37,8 @@
#include "BKE_curve.h"
#include "BKE_curve_render.h"
#include "BKE_displist_render.h"
#include "GPU_batch.h"
#define SELECT 1
@@ -173,6 +175,8 @@ enum {
CU_DATATYPE_OVERLAY = 1 << 1,
/* Edit-mode normals */
CU_DATATYPE_NORMAL = 1 << 2,
/* Geometry */
CU_DATATYPE_SURFACE = 1 << 3,
};
/*
@@ -297,6 +301,10 @@ typedef struct CurveBatchCache {
Batch *verts;
} overlay;
struct {
Batch *batch;
} surface;
/* settings to determine if cache is invalid */
bool is_dirty;
@@ -410,6 +418,10 @@ void BKE_curve_batch_cache_clear(Curve *cu)
BATCH_DISCARD_ALL_SAFE(cache->overlay.verts);
BATCH_DISCARD_ALL_SAFE(cache->overlay.edges);
if (cache->surface.batch) {
BATCH_DISCARD_ALL_SAFE(cache->surface.batch);
}
if (cache->wire.batch) {
BATCH_DISCARD_ALL_SAFE(cache->wire.batch);
cache->wire.verts = NULL;
@@ -759,6 +771,15 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
curve_render_data_free(rdata);
}
static Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
{
BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
if (cache->surface.batch == NULL) {
cache->surface.batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
}
return cache->surface.batch;
}
Batch *BKE_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
@@ -825,3 +846,19 @@ Batch *BKE_curve_batch_cache_get_overlay_verts(Curve *cu)
return cache->overlay.verts;
}
struct Batch *BKE_curve_batch_cache_get_triangles_with_normals(
struct Curve *cu, struct CurveCache *ob_curve_cache)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
if (cache->surface.batch == NULL) {
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
curve_batch_cache_get_pos_and_normals(rdata, cache);
curve_render_data_free(rdata);
}
return cache->surface.batch;
}

View File

@@ -0,0 +1,167 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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.
*
* The Original Code is Copyright (C) 2017 by Blender Foundation.
* All rights reserved.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/displist_render.c
* \ingroup bke
*
* \brief DispList API for render engines
*
* \note DispList may be removed soon! This is a utility for object types that use render.
*/
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
#include "DNA_curve_types.h"
#include "BKE_displist.h"
#include "BKE_displist_render.h"
#include "GPU_batch.h"
static int dl_vert_len(const DispList *dl)
{
switch (dl->type) {
case DL_INDEX3:
case DL_INDEX4:
return dl->nr;
case DL_SURF:
return dl->parts * dl->nr;
}
return 0;
}
static int dl_tri_len(const DispList *dl)
{
switch (dl->type) {
case DL_INDEX3:
return dl->parts;
case DL_INDEX4:
return dl->parts * 2;
case DL_SURF:
return dl->totindex * 2;
}
return 0;
}
/* see: displist_get_allverts */
static int curve_render_surface_vert_len_get(const ListBase *lb)
{
int vert_len = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
vert_len += dl_vert_len(dl);
}
return vert_len;
}
static int curve_render_surface_tri_len_get(const ListBase *lb)
{
int tri_len = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
tri_len += dl_tri_len(dl);
}
return tri_len;
}
Batch *BLI_displist_batch_calc_surface(ListBase *lb)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
if (tri_len == 0) {
return NULL;
}
static VertexFormat format = { 0 };
static unsigned int pos_id, nor_id;
if (format.attrib_ct == 0) {
/* initialize vertex format */
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
}
const int vert_len = curve_render_surface_vert_len_get(lb);
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
{
const int vbo_len_capacity = vert_len;
int vbo_len_used = 0;
VertexBuffer_allocate_data(vbo, vbo_len_capacity);
BKE_displist_normals_add(lb);
for (const DispList *dl = lb->first; dl; dl = dl->next) {
const bool ndata_is_single = dl->type == DL_INDEX3;
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
const float *fp_co = dl->verts;
const float *fp_no = dl->nors;
const int vbo_end = vbo_len_used + dl_vert_len(dl);
while (vbo_len_used < vbo_end) {
VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used, fp_co);
if (fp_no) {
VertexBuffer_set_attrib(vbo, nor_id, vbo_len_used, fp_no);
if (ndata_is_single == false) {
fp_no += 3;
}
}
fp_co += 3;
vbo_len_used += 1;
}
}
}
}
{
ElementListBuilder elb;
ElementListBuilder_init(&elb, PRIM_TRIANGLES, tri_len, vert_len);
int ofs = 0;
int tri_len_used = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
if (dl->type == DL_INDEX3) {
const int *idx = dl->index;
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++) {
add_triangle_vertices(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
tri_len_used += 1;
idx += 3;
}
}
else if (ELEM(dl->type, DL_INDEX4, DL_SURF)) {
const int *idx = dl->index;
const int i_end = dl->totindex;
for (int i = 0; i < i_end; i++) {
add_triangle_vertices(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
tri_len_used += 1;
add_triangle_vertices(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
tri_len_used += 1;
idx += 4;
}
}
ofs += dl_vert_len(dl);
}
}
return Batch_create(PRIM_TRIANGLES, vbo, ElementList_build(&elb));
}
}

View File

@@ -353,6 +353,8 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
BKE_lattice_batch_cache_dirty(ob->data);
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
BKE_curve_batch_cache_dirty(ob->data);
break;
}

View File

@@ -564,7 +564,6 @@ static void CLAY_cache_populate(void *vedata, Object *ob)
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
struct Batch *geom;
DRWShadingGroup *clay_shgrp;
if (!DRW_is_object_renderable(ob))
@@ -573,10 +572,9 @@ static void CLAY_cache_populate(void *vedata, Object *ob)
IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
/* TODO all renderable */
if (ob->type == OB_MESH) {
geom = DRW_cache_mesh_surface_get(ob);
struct Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
/* Depth Prepass */
DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);

View File

@@ -436,10 +436,10 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
if (ob->type == OB_MESH) {
struct Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
struct Batch *geom = DRW_cache_mesh_surface_get(ob);
/* Depth Prepass */
DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);

View File

@@ -450,6 +450,30 @@ Batch *DRW_cache_screenspace_circle_get(void)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Common Object API
* \{ */
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;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Empties
@@ -1582,7 +1606,7 @@ Batch *DRW_cache_mesh_verts_get(Object *ob)
Batch *DRW_cache_curve_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
BLI_assert(ELEM(ob->type, OB_CURVE, OB_FONT));
struct Curve *cu = ob->data;
return BKE_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
@@ -1612,6 +1636,46 @@ Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
return BKE_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 BKE_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Font
* \{ */
Batch *DRW_cache_text_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
return BKE_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Surface
* \{ */
Batch *DRW_cache_surf_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return BKE_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lattice

View File

@@ -38,6 +38,9 @@ struct Batch *DRW_cache_single_line_get(void);
struct Batch *DRW_cache_single_line_endpoints_get(void);
struct Batch *DRW_cache_screenspace_circle_get(void);
/* Common Object */
struct Batch *DRW_cache_object_surface_get(struct Object *ob);
/* Empties */
struct Batch *DRW_cache_plain_axes_get(void);
struct Batch *DRW_cache_single_arrow_get(void);
@@ -93,6 +96,14 @@ struct Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
struct Batch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
struct Batch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
struct Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
struct Batch *DRW_cache_curve_surface_get(struct Object *ob);
struct Batch *DRW_cache_curve_surface_verts_get(struct Object *ob);
/* Font */
struct Batch *DRW_cache_text_surface_get(struct Object *ob);
/* Surface */
struct Batch *DRW_cache_surf_surface_get(struct Object *ob);
/* Lattice */
struct Batch *DRW_cache_lattice_verts_get(struct Object *ob);

View File

@@ -30,6 +30,7 @@
/* If builtin shaders are needed */
#include "GPU_shader.h"
#include "GPU_batch.h"
#include "draw_common.h"
@@ -60,6 +61,7 @@ typedef struct EDIT_CURVE_PassList {
/* Declare all passes here and init them in
* EDIT_CURVE_cache_init().
* Only contains (DRWPass *) */
struct DRWPass *surface_pass;
struct DRWPass *wire_pass;
struct DRWPass *overlay_edge_pass;
struct DRWPass *overlay_vert_pass;
@@ -105,6 +107,8 @@ static struct {
* Add sources to source/blender/draw/modes/shaders
* init in EDIT_CURVE_engine_init();
* free in EDIT_CURVE_engine_free(); */
struct GPUShader *surface_sh;
struct GPUShader *wire_sh;
struct GPUShader *overlay_edge_sh; /* handles and nurbs control cage */
@@ -116,6 +120,8 @@ typedef struct g_data {
/* This keeps the references of the shading groups for
* easy access in EDIT_CURVE_cache_populate() */
DRWShadingGroup *surface_shgrp;
/* resulting curve as 'wire' for curves (and optionally normals) */
DRWShadingGroup *wire_shgrp;
@@ -151,6 +157,11 @@ static void EDIT_CURVE_engine_init(void *vedata)
* tex, 2);
*/
if (!e_data.surface_sh) {
e_data.surface_sh = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING);
}
if (!e_data.wire_sh) {
e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
}
@@ -180,6 +191,12 @@ static void EDIT_CURVE_cache_init(void *vedata)
}
{
/* Surface */
psl->surface_pass = DRW_pass_create(
"Surface",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
stl->g_data->surface_shgrp = DRW_shgroup_create(e_data.surface_sh, psl->surface_pass);
/* Center-Line (wire) */
psl->wire_pass = DRW_pass_create(
"Curve Wire",
@@ -222,7 +239,13 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
/* Get geometry cache */
struct Batch *geom;
// geom = DRW_cache_mesh_surface_get(ob);
geom = DRW_cache_curve_surface_get(ob);
if (geom) {
Batch_set_builtin_program(geom, GPU_SHADER_SIMPLE_LIGHTING);
Batch_Uniform4f(geom, "color", 1, 1, 1, 1);
Batch_Uniform3f(geom, "light", 0, 0, 1);
DRW_shgroup_call_add(stl->g_data->surface_shgrp, geom, ob->obmat);
}
geom = DRW_cache_curve_edge_wire_get(ob);
DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
@@ -276,6 +299,7 @@ static void EDIT_CURVE_draw_scene(void *vedata)
*/
/* ... or just render passes on default framebuffer. */
DRW_draw_pass(psl->surface_pass);
DRW_draw_pass(psl->wire_pass);
DRW_draw_pass(psl->overlay_edge_pass);
DRW_draw_pass(psl->overlay_vert_pass);

View File

@@ -1162,22 +1162,24 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
//bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
switch (ob->type) {
case OB_MESH:
{
Object *obedit = scene->obedit;
if (ob != obedit) {
if (do_outlines) {
struct Batch *geom = DRW_cache_mesh_surface_get(ob);
int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_shgroup_or(stl, theme_id, NULL);
if (shgroup != NULL) {
DRW_shgroup_call_add(shgroup, geom, ob->obmat);
}
if (do_outlines) {
Object *obedit = scene->obedit;
if (ob != obedit) {
struct Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_shgroup_or(stl, theme_id, NULL);
if (shgroup != NULL) {
DRW_shgroup_call_add(shgroup, geom, ob->obmat);
}
}
break;
}
}
switch (ob->type) {
case OB_MESH:
case OB_SURF:
break;
case OB_LATTICE:
{
Object *obedit = scene->obedit;