Commit of the sculpt patch (#19672). Further development will be in this branch until we merge to trunk.
This commit is contained in:
@@ -204,7 +204,7 @@ struct DerivedMesh {
|
||||
*
|
||||
* Also called for *final* editmode DerivedMeshes
|
||||
*/
|
||||
void (*drawFacesSolid)(DerivedMesh *dm,
|
||||
void (*drawFacesSolid)(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4],
|
||||
int (*setMaterial)(int, void *attribs));
|
||||
|
||||
/* Draw all faces
|
||||
|
||||
@@ -34,6 +34,7 @@ struct MultireModifierData;
|
||||
struct MVert;
|
||||
struct Object;
|
||||
struct Paint;
|
||||
struct PBVH;
|
||||
struct Scene;
|
||||
struct StrokeCache;
|
||||
|
||||
@@ -76,8 +77,10 @@ typedef struct SculptSession {
|
||||
|
||||
/* Used temporarily per-stroke */
|
||||
float *vertexcosnos;
|
||||
ListBase damaged_rects;
|
||||
ListBase damaged_verts;
|
||||
|
||||
/* Partial redraw */
|
||||
struct PBVH *tree;
|
||||
int partial_redraw;
|
||||
|
||||
/* Used to cache the render of the active texture */
|
||||
unsigned int texcache_side, *texcache, texcache_actual;
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_edgehash.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_pbvh.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@@ -360,7 +360,68 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
|
||||
static int nodes_drawn = 0;
|
||||
static int is_partial = 0;
|
||||
/* XXX: Just a temporary replacement for the real drawing code */
|
||||
static void draw_partial_cb(const int *face_indices,
|
||||
const int *vert_indices,
|
||||
int totface, int totvert, void *data_v)
|
||||
{
|
||||
/* XXX: Just some quick code to show leaf nodes in different colors */
|
||||
/*float col[3]; int i;
|
||||
if(is_partial) {
|
||||
col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
|
||||
}
|
||||
else {
|
||||
srand((long long)data_v);
|
||||
for(i = 0; i < 3; ++i)
|
||||
col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
|
||||
}
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
|
||||
|
||||
glColor3f(1, 0, 0);*/
|
||||
GPU_draw_buffers(data_v);
|
||||
++nodes_drawn;
|
||||
}
|
||||
|
||||
int find_all(float bb_min[3], float bb_max[3], void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Adapted from:
|
||||
http://www.gamedev.net/community/forums/topic.asp?topic_id=512123
|
||||
Returns true if the AABB is at least partially within the frustum
|
||||
(ok, not a real frustum), false otherwise.
|
||||
*/
|
||||
int planes_contain_AABB(float bb_min[3], float bb_max[3], void *data)
|
||||
{
|
||||
float (*planes)[4] = data;
|
||||
int i, axis;
|
||||
float vmin[3], vmax[3];
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
for(axis = 0; axis < 3; ++axis) {
|
||||
if(planes[i][axis] > 0) {
|
||||
vmin[axis] = bb_min[axis];
|
||||
vmax[axis] = bb_max[axis];
|
||||
}
|
||||
else {
|
||||
vmin[axis] = bb_max[axis];
|
||||
vmax[axis] = bb_min[axis];
|
||||
}
|
||||
}
|
||||
|
||||
if(Inpf(planes[i], vmin) + planes[i][3] > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree,
|
||||
float (*partial_redraw_planes)[4],
|
||||
int (*setMaterial)(int, void *attribs))
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
|
||||
MVert *mvert = cddm->mvert;
|
||||
@@ -376,6 +437,32 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a
|
||||
glVertex3fv(mvert[index].co); \
|
||||
}
|
||||
|
||||
if(tree) {
|
||||
BLI_pbvh_search(tree, BLI_pbvh_update_search_cb,
|
||||
PBVH_NodeData, NULL, NULL,
|
||||
PBVH_SEARCH_UPDATE);
|
||||
|
||||
if(partial_redraw_planes) {
|
||||
BLI_pbvh_search(tree, planes_contain_AABB,
|
||||
partial_redraw_planes,
|
||||
draw_partial_cb, PBVH_DrawData,
|
||||
PBVH_SEARCH_MODIFIED);
|
||||
}
|
||||
else {
|
||||
BLI_pbvh_search(tree, find_all, NULL,
|
||||
draw_partial_cb, PBVH_DrawData,
|
||||
PBVH_SEARCH_NORMAL);
|
||||
|
||||
}
|
||||
|
||||
is_partial = !!partial_redraw_planes;
|
||||
|
||||
//printf("nodes drawn=%d\n", nodes_drawn);
|
||||
nodes_drawn = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( GPU_buffer_legacy(dm) ) {
|
||||
DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
|
||||
glBegin(glmode = GL_QUADS);
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_pbvh.h"
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
@@ -228,8 +230,6 @@ void free_sculptsession(SculptSession **ssp)
|
||||
{
|
||||
if(ssp && *ssp) {
|
||||
SculptSession *ss = *ssp;
|
||||
if(ss->projverts)
|
||||
MEM_freeN(ss->projverts);
|
||||
|
||||
if(ss->fmap)
|
||||
MEM_freeN(ss->fmap);
|
||||
@@ -246,6 +246,12 @@ void free_sculptsession(SculptSession **ssp)
|
||||
if(ss->mesh_co_orig)
|
||||
MEM_freeN(ss->mesh_co_orig);
|
||||
|
||||
if(ss->tree)
|
||||
BLI_pbvh_free(ss->tree);
|
||||
|
||||
if(ss->face_normals)
|
||||
MEM_freeN(ss->face_normals);
|
||||
|
||||
MEM_freeN(ss);
|
||||
|
||||
*ssp = NULL;
|
||||
|
||||
@@ -1615,7 +1615,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
|
||||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
|
||||
static void ccgDM_drawFacesSolid(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) {
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
|
||||
|
||||
62
source/blender/blenlib/BLI_pbvh.h
Normal file
62
source/blender/blenlib/BLI_pbvh.h
Normal file
@@ -0,0 +1,62 @@
|
||||
struct MFace;
|
||||
struct MVert;
|
||||
struct PBVH;
|
||||
|
||||
/* Returns 1 if the search should continue from this node, 0 otherwise */
|
||||
typedef int (*BLI_pbvh_SearchCallback)(float bb_min[3], float bb_max[3],
|
||||
void *data);
|
||||
|
||||
typedef void (*BLI_pbvh_HitCallback)(const int *face_indices,
|
||||
const int *vert_indices,
|
||||
int totface, int totvert, void *data);
|
||||
int BLI_pbvh_search_range(float bb_min[3], float bb_max[3], void *data_v);
|
||||
|
||||
typedef enum {
|
||||
PBVH_SEARCH_NORMAL,
|
||||
|
||||
/* When the callback returns a 1 for a leaf node, that node will be
|
||||
marked as modified */
|
||||
PBVH_SEARCH_MARK_MODIFIED,
|
||||
|
||||
/* Update gpu data for modified nodes. Also clears the Modified flag. */
|
||||
PBVH_SEARCH_MODIFIED,
|
||||
|
||||
|
||||
PBVH_SEARCH_UPDATE
|
||||
} PBVH_SearchMode;
|
||||
|
||||
/* Pass the node as data to the callback */
|
||||
#define PBVH_NodeData (void*)0xa
|
||||
/* Pass the draw buffers as data to the callback */
|
||||
#define PBVH_DrawData (void*)0xb
|
||||
|
||||
void BLI_pbvh_search(struct PBVH *bvh, BLI_pbvh_SearchCallback scb,
|
||||
void *search_data, BLI_pbvh_HitCallback hcb,
|
||||
void *hit_data, PBVH_SearchMode mode);
|
||||
|
||||
/* The hit callback is called for all leaf nodes intersecting the ray;
|
||||
it's up to the callback to find the primitive within the leaves that is
|
||||
hit first */
|
||||
void BLI_pbvh_raycast(struct PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
|
||||
float ray_start[3], float ray_normal[3]);
|
||||
|
||||
|
||||
int BLI_pbvh_update_search_cb(float bb_min[3], float bb_max[3], void *data_v);
|
||||
|
||||
/* Get the bounding box around all nodes that have been marked as modified. */
|
||||
void BLI_pbvh_modified_bounding_box(struct PBVH *bvh,
|
||||
float bb_min[3], float bb_max[3]);
|
||||
void BLI_pbvh_reset_modified_bounding_box(struct PBVH *bvh);
|
||||
|
||||
/* Lock is off by default, turn on to stop redraw from clearing the modified
|
||||
flag from nodes */
|
||||
void BLI_pbvh_toggle_modified_lock(struct PBVH *bvh);
|
||||
|
||||
|
||||
|
||||
struct PBVH *BLI_pbvh_new(BLI_pbvh_HitCallback update_cb, void *update_cb_data);
|
||||
void BLI_pbvh_build(struct PBVH *bvh, struct MFace *faces, struct MVert *verts,
|
||||
int totface, int totvert);
|
||||
void BLI_pbvh_free(struct PBVH *bvh);
|
||||
|
||||
void BLI_pbvh_set_source(struct PBVH *bvh, struct MVert *, struct MFace *mface);
|
||||
@@ -28,6 +28,7 @@ FILE(GLOB SRC intern/*.c)
|
||||
|
||||
SET(INC
|
||||
. ../makesdna ../blenkernel ../../../intern/guardedalloc ../include
|
||||
../gpu
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
${ZLIB_INC}
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ Import ('env')
|
||||
sources = env.Glob('intern/*.c')
|
||||
|
||||
cflags=''
|
||||
incs = '. ../makesdna ../blenkernel #/intern/guardedalloc ../editors/include'
|
||||
incs = '. ../makesdna ../blenkernel #/intern/guardedalloc ../editors/include ../gpu'
|
||||
incs += ' ' + env['BF_FREETYPE_INC']
|
||||
incs += ' ' + env['BF_ZLIB_INC']
|
||||
defs = ''
|
||||
|
||||
@@ -4324,7 +4324,7 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo
|
||||
|
||||
Crossf(p, d, e2);
|
||||
a = Inpf(e1, p);
|
||||
if ((a > -0.000001) && (a < 0.000001)) return 0;
|
||||
if ((a > -FLT_EPSILON) && (a < FLT_EPSILON)) return 0;
|
||||
f = 1.0f/a;
|
||||
|
||||
VecSubf(s, p1, v0);
|
||||
|
||||
665
source/blender/blenlib/intern/pbvh.c
Normal file
665
source/blender/blenlib/intern/pbvh.c
Normal file
@@ -0,0 +1,665 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_pbvh.h"
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "gpu_buffers.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LEAF_LIMIT 10000
|
||||
|
||||
//#define PERFCNTRS
|
||||
|
||||
/* Bitmap */
|
||||
typedef char* BLI_bitmap;
|
||||
|
||||
BLI_bitmap BLI_bitmap_new(int tot)
|
||||
{
|
||||
return MEM_callocN((tot >> 3) + 1, "BLI bitmap");
|
||||
}
|
||||
|
||||
int BLI_bitmap_get(BLI_bitmap b, int index)
|
||||
{
|
||||
return b[index >> 3] & (1 << (index & 7));
|
||||
}
|
||||
|
||||
void BLI_bitmap_set(BLI_bitmap b, int index)
|
||||
{
|
||||
b[index >> 3] |= (1 << (index & 7));
|
||||
}
|
||||
|
||||
void BLI_bitmap_clear(BLI_bitmap b, int index)
|
||||
{
|
||||
b[index >> 3] &= ~(1 << (index & 7));
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PBVH_Leaf = 1,
|
||||
PBVH_Modified = 2
|
||||
} NodeFlags;
|
||||
|
||||
/* Axis-aligned bounding box */
|
||||
typedef struct {
|
||||
float bmin[3], bmax[3];
|
||||
} BB;
|
||||
|
||||
/* Axis-aligned bounding box with centroid */
|
||||
typedef struct {
|
||||
float bmin[3], bmax[3], bcentroid[3];
|
||||
} BBC;
|
||||
|
||||
typedef struct {
|
||||
/* Opaque handle for drawing code */
|
||||
void *draw_buffers;
|
||||
|
||||
int *vert_indices;
|
||||
|
||||
/* Voxel bounds */
|
||||
BB vb;
|
||||
|
||||
/* For internal nodes */
|
||||
int children_offset;
|
||||
|
||||
/* Range of faces used in the node */
|
||||
int face_offset;
|
||||
|
||||
unsigned short totface;
|
||||
unsigned short uniq_verts, face_verts;
|
||||
|
||||
char flag;
|
||||
} Node;
|
||||
|
||||
typedef struct PBVH {
|
||||
Node *nodes;
|
||||
int node_mem_count, totnode;
|
||||
|
||||
int *face_indices;
|
||||
int totface;
|
||||
|
||||
BB modified_bb;
|
||||
|
||||
BLI_pbvh_HitCallback update_cb;
|
||||
void *update_cb_data;
|
||||
|
||||
/* Mesh data */
|
||||
MVert *verts;
|
||||
MFace *faces;
|
||||
|
||||
int modified_lock;
|
||||
|
||||
/* Only used during BVH build and update,
|
||||
don't need to remain valid after */
|
||||
BLI_bitmap vert_bitmap;
|
||||
|
||||
#ifdef PERFCNTRS
|
||||
int perf_modified;
|
||||
#endif
|
||||
} PBVH;
|
||||
|
||||
static void BB_reset(BB *bb)
|
||||
{
|
||||
bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
|
||||
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
|
||||
}
|
||||
|
||||
/* Expand the bounding box to include a new coordinate */
|
||||
static void BB_expand(BB *bb, float co[3])
|
||||
{
|
||||
if(co[0] < bb->bmin[0]) bb->bmin[0] = co[0];
|
||||
if(co[1] < bb->bmin[1]) bb->bmin[1] = co[1];
|
||||
if(co[2] < bb->bmin[2]) bb->bmin[2] = co[2];
|
||||
|
||||
if(co[0] > bb->bmax[0]) bb->bmax[0] = co[0];
|
||||
if(co[1] > bb->bmax[1]) bb->bmax[1] = co[1];
|
||||
if(co[2] > bb->bmax[2]) bb->bmax[2] = co[2];
|
||||
}
|
||||
|
||||
/* Expand the bounding box to include another bounding box */
|
||||
static void BB_expand_with_bb(BB *bb, BB *bb2)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 3; ++i) {
|
||||
bb->bmin[i] = MIN2(bb->bmin[i], bb2->bmin[i]);
|
||||
bb->bmax[i] = MAX2(bb->bmax[i], bb2->bmax[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
|
||||
static int BB_widest_axis(BB *bb)
|
||||
{
|
||||
float dim[3];
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 3; ++i)
|
||||
dim[i] = bb->bmax[i] - bb->bmin[i];
|
||||
|
||||
if(dim[0] > dim[1]) {
|
||||
if(dim[0] > dim[2])
|
||||
return 0;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
if(dim[1] > dim[2])
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void BBC_update_centroid(BBC *bbc)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 3; ++i)
|
||||
bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f;
|
||||
}
|
||||
|
||||
/* Not recursive */
|
||||
static void update_node_vb(PBVH *bvh, Node *node)
|
||||
{
|
||||
BB_reset(&node->vb);
|
||||
|
||||
if(node->flag & PBVH_Leaf) {
|
||||
int i, j;
|
||||
for(i = node->face_offset + node->totface - 1;
|
||||
i >= node->face_offset; --i) {
|
||||
MFace *f = bvh->faces + bvh->face_indices[i];
|
||||
const int sides = f->v4 ? 4 : 3;
|
||||
|
||||
for(j = 0; j < sides; ++j)
|
||||
BB_expand(&node->vb,
|
||||
bvh->verts[*((&f->v1) + j)].co);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BB_expand_with_bb(&node->vb,
|
||||
&bvh->nodes[node->children_offset].vb);
|
||||
BB_expand_with_bb(&node->vb,
|
||||
&bvh->nodes[node->children_offset + 1].vb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adapted from BLI_kdopbvh.c */
|
||||
/* Returns the index of the first element on the right of the partition */
|
||||
static int partition_indices(int *face_indices, int lo, int hi, int axis,
|
||||
float mid, BBC *prim_bbc)
|
||||
{
|
||||
int i=lo, j=hi;
|
||||
for(;;) {
|
||||
for(; prim_bbc[face_indices[i]].bcentroid[axis] < mid; i++);
|
||||
for(; mid < prim_bbc[face_indices[j]].bcentroid[axis]; j--);
|
||||
|
||||
if(!(i < j))
|
||||
return i;
|
||||
|
||||
SWAP(int, face_indices[i], face_indices[j]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void check_partitioning(int *face_indices, int lo, int hi, int axis,
|
||||
float mid, BBC *prim_bbc, int index_of_2nd_partition)
|
||||
{
|
||||
int i;
|
||||
for(i = lo; i <= hi; ++i) {
|
||||
const float c = prim_bbc[face_indices[i]].bcentroid[axis];
|
||||
|
||||
if((i < index_of_2nd_partition && c > mid) ||
|
||||
(i > index_of_2nd_partition && c < mid)) {
|
||||
printf("fail\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void grow_nodes(PBVH *bvh, int totnode)
|
||||
{
|
||||
if(totnode > bvh->node_mem_count) {
|
||||
Node *prev = bvh->nodes;
|
||||
bvh->node_mem_count *= 1.33;
|
||||
if(bvh->node_mem_count < totnode)
|
||||
bvh->node_mem_count = totnode;
|
||||
bvh->nodes = MEM_callocN(sizeof(Node) * bvh->node_mem_count,
|
||||
"bvh nodes");
|
||||
memcpy(bvh->nodes, prev, bvh->totnode * sizeof(Node));
|
||||
MEM_freeN(prev);
|
||||
}
|
||||
|
||||
bvh->totnode = totnode;
|
||||
}
|
||||
|
||||
/* Add a vertex to the map, with a positive value for unique vertices and
|
||||
a negative value for additional vertices */
|
||||
static void map_insert_vert(PBVH *bvh, GHash *map,
|
||||
unsigned short *face_verts,
|
||||
unsigned short *uniq_verts, int vertex)
|
||||
{
|
||||
void *value, *key = SET_INT_IN_POINTER(vertex);
|
||||
|
||||
if(!BLI_ghash_haskey(map, key)) {
|
||||
if(BLI_bitmap_get(bvh->vert_bitmap, vertex)) {
|
||||
value = SET_INT_IN_POINTER(-(*face_verts) - 1);
|
||||
++(*face_verts);
|
||||
}
|
||||
else {
|
||||
BLI_bitmap_set(bvh->vert_bitmap, vertex);
|
||||
value = SET_INT_IN_POINTER(*uniq_verts);
|
||||
++(*uniq_verts);
|
||||
}
|
||||
|
||||
BLI_ghash_insert(map, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find vertices used by the faces in this node and update the draw buffers */
|
||||
static void build_leaf_node(PBVH *bvh, Node *node)
|
||||
{
|
||||
GHashIterator *iter;
|
||||
GHash *map;
|
||||
int i, j;
|
||||
|
||||
map = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
|
||||
|
||||
node->uniq_verts = node->face_verts = 0;
|
||||
|
||||
for(i = node->face_offset + node->totface - 1;
|
||||
i >= node->face_offset; --i) {
|
||||
MFace *f = bvh->faces + bvh->face_indices[i];
|
||||
int sides = f->v4 ? 4 : 3;
|
||||
|
||||
for(j = 0; j < sides; ++j) {
|
||||
map_insert_vert(bvh, map, &node->face_verts,
|
||||
&node->uniq_verts, (&f->v1)[j]);
|
||||
}
|
||||
}
|
||||
|
||||
node->vert_indices = MEM_callocN(sizeof(int) *
|
||||
(node->uniq_verts + node->face_verts),
|
||||
"bvh node vert indices");
|
||||
|
||||
/* Build the vertex list, unique verts first */
|
||||
for(iter = BLI_ghashIterator_new(map), i = 0;
|
||||
!BLI_ghashIterator_isDone(iter);
|
||||
BLI_ghashIterator_step(iter), ++i) {
|
||||
void *value = BLI_ghashIterator_getValue(iter);
|
||||
int ndx = GET_INT_FROM_POINTER(value);
|
||||
|
||||
if(ndx < 0)
|
||||
ndx = -ndx + node->uniq_verts - 1;
|
||||
|
||||
node->vert_indices[ndx] =
|
||||
GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(iter));
|
||||
}
|
||||
|
||||
node->draw_buffers =
|
||||
GPU_build_buffers(map, bvh->verts, bvh->faces,
|
||||
bvh->face_indices + node->face_offset,
|
||||
node->totface, node->vert_indices,
|
||||
node->uniq_verts,
|
||||
node->uniq_verts + node->face_verts);
|
||||
|
||||
BLI_ghash_free(map, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Recursively build a node in the tree
|
||||
|
||||
vb is the voxel box around all of the primitives contained in
|
||||
this node.
|
||||
|
||||
cb is the bounding box around all the centroids of the primitives
|
||||
contained in this node
|
||||
|
||||
offset and start indicate a range in the array of primitive indices
|
||||
*/
|
||||
|
||||
void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
|
||||
int offset, int count)
|
||||
{
|
||||
int i, axis, end;
|
||||
BB cb_backing;
|
||||
|
||||
/* Decide whether this is a leaf or not */
|
||||
if(count <= LEAF_LIMIT) {
|
||||
bvh->nodes[node_index].flag |= PBVH_Leaf;
|
||||
|
||||
bvh->nodes[node_index].face_offset = offset;
|
||||
bvh->nodes[node_index].totface = count;
|
||||
|
||||
/* Still need vb for searches */
|
||||
BB_reset(&bvh->nodes[node_index].vb);
|
||||
for(i = offset + count - 1; i >= offset; --i) {
|
||||
BB_expand_with_bb(&bvh->nodes[node_index].vb,
|
||||
(BB*)(prim_bbc +
|
||||
bvh->face_indices[i]));
|
||||
}
|
||||
|
||||
build_leaf_node(bvh, bvh->nodes + node_index);
|
||||
|
||||
/* Done with this subtree */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
BB_reset(&bvh->nodes[node_index].vb);
|
||||
bvh->nodes[node_index].children_offset = bvh->totnode;
|
||||
grow_nodes(bvh, bvh->totnode + 2);
|
||||
|
||||
if(!cb) {
|
||||
cb = &cb_backing;
|
||||
BB_reset(cb);
|
||||
for(i = offset + count - 1; i >= offset; --i)
|
||||
BB_expand(cb, prim_bbc[bvh->face_indices[i]].bcentroid);
|
||||
}
|
||||
}
|
||||
|
||||
axis = BB_widest_axis(cb);
|
||||
|
||||
for(i = offset + count - 1; i >= offset; --i) {
|
||||
BB_expand_with_bb(&bvh->nodes[node_index].vb,
|
||||
(BB*)(prim_bbc + bvh->face_indices[i]));
|
||||
}
|
||||
|
||||
end = partition_indices(bvh->face_indices, offset, offset + count - 1,
|
||||
axis,
|
||||
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
|
||||
prim_bbc);
|
||||
check_partitioning(bvh->face_indices, offset, offset + count - 1,
|
||||
axis,
|
||||
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
|
||||
prim_bbc, end);
|
||||
|
||||
build_sub(bvh, bvh->nodes[node_index].children_offset, NULL,
|
||||
prim_bbc, offset, end - offset);
|
||||
build_sub(bvh, bvh->nodes[node_index].children_offset + 1, NULL,
|
||||
prim_bbc, end, offset + count - end);
|
||||
}
|
||||
|
||||
/* Do a full rebuild */
|
||||
void BLI_pbvh_build(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert)
|
||||
{
|
||||
BBC *prim_bbc = NULL;
|
||||
BB cb;
|
||||
int i, j;
|
||||
|
||||
if(totface != bvh->totface) {
|
||||
bvh->totface = totface;
|
||||
if(bvh->nodes) MEM_freeN(bvh->nodes);
|
||||
if(bvh->face_indices) MEM_freeN(bvh->face_indices);
|
||||
bvh->face_indices = MEM_callocN(sizeof(int) * totface,
|
||||
"bvh face indices");
|
||||
for(i = 0; i < totface; ++i)
|
||||
bvh->face_indices[i] = i;
|
||||
bvh->totnode = 0;
|
||||
if(bvh->node_mem_count < 100) {
|
||||
bvh->node_mem_count = 100;
|
||||
bvh->nodes = MEM_callocN(sizeof(Node) *
|
||||
bvh->node_mem_count,
|
||||
"bvh initial nodes");
|
||||
}
|
||||
}
|
||||
|
||||
bvh->faces = faces;
|
||||
bvh->verts = verts;
|
||||
bvh->vert_bitmap = BLI_bitmap_new(totvert);
|
||||
|
||||
BB_reset(&bvh->modified_bb);
|
||||
|
||||
BB_reset(&cb);
|
||||
|
||||
/* For each face, store the AABB and the AABB centroid */
|
||||
prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
|
||||
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = faces + i;
|
||||
const int sides = f->v4 ? 4 : 3;
|
||||
BBC *bbc = prim_bbc + i;
|
||||
|
||||
BB_reset((BB*)bbc);
|
||||
|
||||
for(j = 0; j < sides; ++j)
|
||||
BB_expand((BB*)bbc, verts[(&f->v1)[j]].co);
|
||||
|
||||
BBC_update_centroid(bbc);
|
||||
|
||||
BB_expand(&cb, bbc->bcentroid);
|
||||
}
|
||||
|
||||
bvh->totnode = 1;
|
||||
build_sub(bvh, 0, &cb, prim_bbc, 0, totface);
|
||||
|
||||
MEM_freeN(prim_bbc);
|
||||
MEM_freeN(bvh->vert_bitmap);
|
||||
}
|
||||
|
||||
PBVH *BLI_pbvh_new(BLI_pbvh_HitCallback update_cb, void *update_cb_data)
|
||||
{
|
||||
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
|
||||
|
||||
bvh->update_cb = update_cb;
|
||||
bvh->update_cb_data = update_cb_data;
|
||||
|
||||
return bvh;
|
||||
}
|
||||
|
||||
void BLI_pbvh_free(PBVH *bvh)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < bvh->totnode; ++i) {
|
||||
if(bvh->nodes[i].flag & PBVH_Leaf) {
|
||||
GPU_free_buffers(bvh->nodes[i].draw_buffers);
|
||||
MEM_freeN(bvh->nodes[i].vert_indices);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(bvh->nodes);
|
||||
MEM_freeN(bvh->face_indices);
|
||||
MEM_freeN(bvh);
|
||||
}
|
||||
|
||||
void BLI_pbvh_set_source(PBVH *bvh, MVert *mvert, MFace *mface)
|
||||
{
|
||||
bvh->verts = mvert;
|
||||
bvh->faces = mface;
|
||||
}
|
||||
|
||||
static void do_hit_callback(PBVH *bvh, Node *node,
|
||||
BLI_pbvh_HitCallback cb, void *data)
|
||||
{
|
||||
if(cb) {
|
||||
cb(bvh->face_indices + node->face_offset, node->vert_indices,
|
||||
node->totface, node->uniq_verts, data);
|
||||
}
|
||||
}
|
||||
|
||||
static int search_sub(PBVH *bvh, Node *node,
|
||||
BLI_pbvh_SearchCallback scb, void *search_data_f,
|
||||
BLI_pbvh_HitCallback hcb, void *hit_data_f,
|
||||
PBVH_SearchMode mode)
|
||||
{
|
||||
void *search_data = search_data_f;
|
||||
void *hit_data = hit_data_f;
|
||||
|
||||
if(search_data_f == PBVH_NodeData)
|
||||
search_data = &node->flag;
|
||||
if(hit_data_f == PBVH_DrawData)
|
||||
hit_data = node->draw_buffers;
|
||||
|
||||
if(scb(node->vb.bmin, node->vb.bmax, search_data)) {
|
||||
if(node->flag & PBVH_Leaf) {
|
||||
switch(mode) {
|
||||
case PBVH_SEARCH_MARK_MODIFIED:
|
||||
node->flag |= PBVH_Modified;
|
||||
#ifdef PERFCNTRS
|
||||
++bvh->perf_modified;
|
||||
#endif
|
||||
break;
|
||||
case PBVH_SEARCH_MODIFIED:
|
||||
if(node->flag & PBVH_Modified) {
|
||||
if(bvh->update_cb) {
|
||||
do_hit_callback
|
||||
(bvh, node,
|
||||
bvh->update_cb,
|
||||
bvh->update_cb_data);
|
||||
}
|
||||
|
||||
GPU_update_buffers(node->draw_buffers,
|
||||
bvh->verts,
|
||||
node->vert_indices,
|
||||
node->uniq_verts +
|
||||
node->face_verts);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
do_hit_callback(bvh, node, hcb, hit_data);
|
||||
}
|
||||
else {
|
||||
int mod = 0;
|
||||
if(search_sub(bvh, bvh->nodes + node->children_offset,
|
||||
scb, search_data_f, hcb,hit_data_f, mode))
|
||||
mod = 1;
|
||||
if(search_sub(bvh,
|
||||
bvh->nodes + node->children_offset + 1,
|
||||
scb, search_data_f, hcb,hit_data_f, mode))
|
||||
mod = 1;
|
||||
|
||||
if(mod)
|
||||
node->flag |= PBVH_Modified;
|
||||
}
|
||||
}
|
||||
|
||||
if(mode == PBVH_SEARCH_MODIFIED) {
|
||||
#ifdef PERFCNTRS
|
||||
if(node->flag & PBVH_Modified && node->flag & PBVH_Leaf)
|
||||
--bvh->perf_modified;
|
||||
#endif
|
||||
if(!bvh->modified_lock)
|
||||
node->flag &= ~PBVH_Modified;
|
||||
}
|
||||
else if(mode == PBVH_SEARCH_UPDATE) {
|
||||
if(node->flag & PBVH_Modified) {
|
||||
update_node_vb(bvh, node);
|
||||
if(node->flag & PBVH_Leaf)
|
||||
BB_expand_with_bb(&bvh->modified_bb, &node->vb);
|
||||
}
|
||||
}
|
||||
|
||||
return node->flag & PBVH_Modified;
|
||||
}
|
||||
|
||||
void BLI_pbvh_search(PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data,
|
||||
BLI_pbvh_HitCallback hcb, void *hit_data,
|
||||
PBVH_SearchMode mode)
|
||||
{
|
||||
#ifdef PERFCNTRS
|
||||
printf("search mode=%s\n",
|
||||
mode==PBVH_SEARCH_MARK_MODIFIED?"mark-modified":
|
||||
mode==PBVH_SEARCH_MODIFIED?"modified":
|
||||
mode==PBVH_SEARCH_UPDATE?"update":
|
||||
mode==PBVH_SEARCH_NORMAL?"normal":"unknown-mode");
|
||||
if(mode == PBVH_SEARCH_MARK_MODIFIED)
|
||||
bvh->perf_modified = 0;
|
||||
#endif
|
||||
|
||||
search_sub(bvh, bvh->nodes, scb, search_data, hcb, hit_data, mode);
|
||||
#ifdef PERFCNTRS
|
||||
printf("%d nodes marked modified\n", bvh->perf_modified);
|
||||
printf("search complete\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
/* Ray */
|
||||
float start[3];
|
||||
int sign[3];
|
||||
float inv_dir[3];
|
||||
} RaycastData;
|
||||
|
||||
/* Adapted from here: http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */
|
||||
static int ray_aabb_intersect(float bb_min[3], float bb_max[3], void *data_v)
|
||||
{
|
||||
RaycastData *ray = data_v;
|
||||
float bbox[2][3];
|
||||
float tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||
|
||||
VecCopyf(bbox[0], bb_min);
|
||||
VecCopyf(bbox[1], bb_max);
|
||||
|
||||
tmin = (bbox[ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0];
|
||||
tmax = (bbox[1-ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0];
|
||||
|
||||
tymin = (bbox[ray->sign[1]][1] - ray->start[1]) * ray->inv_dir[1];
|
||||
tymax = (bbox[1-ray->sign[1]][1] - ray->start[1]) * ray->inv_dir[1];
|
||||
|
||||
if((tmin > tymax) || (tymin > tmax))
|
||||
return 0;
|
||||
if(tymin > tmin)
|
||||
tmin = tymin;
|
||||
if(tymax < tmax)
|
||||
tmax = tymax;
|
||||
|
||||
tzmin = (bbox[ray->sign[2]][2] - ray->start[2]) * ray->inv_dir[2];
|
||||
tzmax = (bbox[1-ray->sign[2]][2] - ray->start[2]) * ray->inv_dir[2];
|
||||
|
||||
if((tmin > tzmax) || (tzmin > tmax))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
/* XXX: Not sure about this?
|
||||
if(tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
if(tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
return ((tmin < t1) && (tmax > t0));
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
|
||||
float ray_start[3], float ray_normal[3])
|
||||
{
|
||||
RaycastData rcd;
|
||||
|
||||
VecCopyf(rcd.start, ray_start);
|
||||
rcd.inv_dir[0] = 1.0f / ray_normal[0];
|
||||
rcd.inv_dir[1] = 1.0f / ray_normal[1];
|
||||
rcd.inv_dir[2] = 1.0f / ray_normal[2];
|
||||
rcd.sign[0] = rcd.inv_dir[0] < 0;
|
||||
rcd.sign[1] = rcd.inv_dir[1] < 0;
|
||||
rcd.sign[2] = rcd.inv_dir[2] < 0;
|
||||
|
||||
BLI_pbvh_search(bvh, ray_aabb_intersect, &rcd, cb, data,
|
||||
PBVH_SEARCH_NORMAL);
|
||||
}
|
||||
|
||||
int BLI_pbvh_update_search_cb(float bb_min[3], float bb_max[3], void *data_v)
|
||||
{
|
||||
int *data = data_v;
|
||||
|
||||
return ((*data) & PBVH_Modified);
|
||||
}
|
||||
|
||||
void BLI_pbvh_modified_bounding_box(PBVH *bvh, float bb_min[3], float bb_max[3])
|
||||
{
|
||||
VecCopyf(bb_min, bvh->modified_bb.bmin);
|
||||
VecCopyf(bb_max, bvh->modified_bb.bmax);
|
||||
}
|
||||
|
||||
void BLI_pbvh_reset_modified_bounding_box(PBVH *bvh)
|
||||
{
|
||||
BB_reset(&bvh->modified_bb);
|
||||
}
|
||||
|
||||
void BLI_pbvh_toggle_modified_lock(PBVH *bvh)
|
||||
{
|
||||
bvh->modified_lock = !bvh->modified_lock;
|
||||
}
|
||||
@@ -28,11 +28,18 @@
|
||||
#ifndef ED_SCULPT_H
|
||||
#define ED_SCULPT_H
|
||||
|
||||
struct ARegion;
|
||||
struct bContext;
|
||||
struct Object;
|
||||
struct RegionView3D;
|
||||
struct wmKeyConfig;
|
||||
struct wmWindowManager;
|
||||
|
||||
/* sculpt.c */
|
||||
void ED_operatortypes_sculpt(void);
|
||||
void sculpt_get_redraw_planes(float planes[4][4], struct ARegion *ar,
|
||||
struct RegionView3D *rv3d, struct Object *ob);
|
||||
|
||||
|
||||
/* paint_ops.c */
|
||||
void ED_operatortypes_paint(void);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
/* ********* exports for space_view3d/ module ********** */
|
||||
struct ARegion;
|
||||
struct BoundBox;
|
||||
struct View3D;
|
||||
struct RegionView3D;
|
||||
struct ViewContext;
|
||||
@@ -44,6 +45,7 @@ struct ImBuf;
|
||||
struct Scene;
|
||||
struct bContext;
|
||||
struct Main;
|
||||
struct rcti;
|
||||
|
||||
/* for derivedmesh drawing callbacks, for view3d_select, .... */
|
||||
typedef struct ViewContext {
|
||||
@@ -80,6 +82,8 @@ void request_depth_update(struct RegionView3D *rv3d);
|
||||
/* Projection */
|
||||
#define IS_CLIPPED 12000
|
||||
|
||||
void view3d_calculate_clipping(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, struct rcti *rect);
|
||||
|
||||
void project_short(struct ARegion *ar, float *vec, short *adr);
|
||||
void project_short_noclip(struct ARegion *ar, float *vec, short *adr);
|
||||
|
||||
@@ -125,7 +129,7 @@ short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigne
|
||||
void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
|
||||
void view3d_operator_needs_opengl(const struct bContext *C);
|
||||
void view3d_get_view_aligned_coordinate(struct ViewContext *vc, float *fp, short mval[2]);
|
||||
void view3d_get_transformation(struct ViewContext *vc, struct Object *ob, struct bglMats *mats);
|
||||
void view3d_get_transformation(struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats);
|
||||
|
||||
/* XXX should move to arithb.c */
|
||||
int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2);
|
||||
|
||||
@@ -718,6 +718,8 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
|
||||
MultiresModifierData *mmd= ptr.data;
|
||||
|
||||
multiresModifier_subdivide(mmd, ob, 1, 0, mmd->simple);
|
||||
|
||||
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
||||
@@ -362,7 +362,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
|
||||
PE_set_data(C, data);
|
||||
|
||||
view3d_set_viewcontext(C, &data->vc);
|
||||
view3d_get_transformation(&data->vc, data->ob, &data->mats);
|
||||
view3d_get_transformation(data->vc.ar, data->vc.rv3d, data->ob, &data->mats);
|
||||
|
||||
if((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT))
|
||||
view3d_validate_backbuf(&data->vc);
|
||||
|
||||
@@ -43,11 +43,13 @@ struct ARegion;
|
||||
struct VPaint;
|
||||
|
||||
/* paint_stroke.c */
|
||||
typedef int (*StrokeGetLocation)(struct bContext *C, struct PaintStroke *stroke, float location[3], float mouse[2]);
|
||||
typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
|
||||
typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr);
|
||||
typedef void (*StrokeDone)(struct bContext *C, struct PaintStroke *stroke);
|
||||
|
||||
struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeTestStart test_start,
|
||||
struct PaintStroke *paint_stroke_new(struct bContext *C,
|
||||
StrokeGetLocation get_location, StrokeTestStart test_start,
|
||||
StrokeUpdateStep update_step, StrokeDone done);
|
||||
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
|
||||
int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
|
||||
|
||||
@@ -73,6 +73,7 @@ typedef struct PaintStroke {
|
||||
passes over the mesh */
|
||||
int stroke_started;
|
||||
|
||||
StrokeGetLocation get_location;
|
||||
StrokeTestStart test_start;
|
||||
StrokeUpdateStep update_step;
|
||||
StrokeDone done;
|
||||
@@ -118,12 +119,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *customdata)
|
||||
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse[2])
|
||||
{
|
||||
PointerRNA itemptr;
|
||||
float cur_depth, pressure = 1;
|
||||
float center[3];
|
||||
float pressure = 1;
|
||||
float center[3] = {0, 0, 0};
|
||||
PaintStroke *stroke = op->customdata;
|
||||
|
||||
cur_depth = read_cached_depth(&stroke->vc, mouse[0], mouse[1]);
|
||||
view3d_unproject(&stroke->mats, center, mouse[0], mouse[1], cur_depth);
|
||||
/* XXX: can remove the if statement once all modes have this */
|
||||
if(stroke->get_location)
|
||||
stroke->get_location(C, stroke, center, mouse);
|
||||
|
||||
/* Tablet */
|
||||
if(event->custom == EVT_DATA_TABLET) {
|
||||
@@ -208,15 +210,19 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const
|
||||
|
||||
/**** Public API ****/
|
||||
|
||||
PaintStroke *paint_stroke_new(bContext *C, StrokeTestStart test_start,
|
||||
StrokeUpdateStep update_step, StrokeDone done)
|
||||
PaintStroke *paint_stroke_new(bContext *C,
|
||||
StrokeGetLocation get_location,
|
||||
StrokeTestStart test_start,
|
||||
StrokeUpdateStep update_step,
|
||||
StrokeDone done)
|
||||
{
|
||||
PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
|
||||
|
||||
stroke->brush = paint_brush(paint_get_active(CTX_data_scene(C)));
|
||||
view3d_set_viewcontext(C, &stroke->vc);
|
||||
view3d_get_transformation(&stroke->vc, stroke->vc.obact, &stroke->mats);
|
||||
view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats);
|
||||
|
||||
stroke->get_location = get_location;
|
||||
stroke->test_start = test_start;
|
||||
stroke->update_step = update_step;
|
||||
stroke->done = done;
|
||||
@@ -226,7 +232,6 @@ PaintStroke *paint_stroke_new(bContext *C, StrokeTestStart test_start,
|
||||
|
||||
int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
float mouse[2];
|
||||
|
||||
@@ -246,20 +251,20 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
//ED_region_tag_redraw(ar);
|
||||
}
|
||||
|
||||
if(stroke->stroke_started) {
|
||||
if(paint_smooth_stroke(stroke, mouse, event)) {
|
||||
if(paint_space_stroke_enabled(stroke->brush)) {
|
||||
if(!paint_space_stroke(C, op, event, mouse))
|
||||
ED_region_tag_redraw(ar);
|
||||
;//ED_region_tag_redraw(ar);
|
||||
}
|
||||
else
|
||||
paint_brush_stroke_add_step(C, op, event, mouse);
|
||||
}
|
||||
else
|
||||
ED_region_tag_redraw(ar);
|
||||
;//ED_region_tag_redraw(ar);
|
||||
}
|
||||
|
||||
/* TODO: fix hardcoded event here */
|
||||
|
||||
@@ -1493,7 +1493,7 @@ static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
|
||||
static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
|
||||
op->customdata = paint_stroke_new(C, wpaint_stroke_test_start,
|
||||
op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
|
||||
wpaint_stroke_update_step,
|
||||
wpaint_stroke_done);
|
||||
|
||||
@@ -1792,7 +1792,7 @@ static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
|
||||
static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
|
||||
op->customdata = paint_stroke_new(C, vpaint_stroke_test_start,
|
||||
op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
|
||||
vpaint_stroke_update_step,
|
||||
vpaint_stroke_done);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -107,6 +107,7 @@
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_particle.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_sculpt.h"
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
@@ -2691,7 +2692,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
|
||||
drawFacesSolid() doesn't draw the transparent faces */
|
||||
if(ob->dtx & OB_DRAWTRANSP) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
dm->drawFacesSolid(dm, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
GPU_disable_material();
|
||||
}
|
||||
@@ -2710,7 +2711,7 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
|
||||
static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
Mesh *me = ob->data;
|
||||
@@ -2783,7 +2784,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
}
|
||||
}
|
||||
else if(dt==OB_SOLID) {
|
||||
if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
|
||||
if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
|
||||
draw_mesh_object_outline(v3d, ob, dm);
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
|
||||
@@ -2791,7 +2792,21 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
glEnable(GL_LIGHTING);
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
|
||||
dm->drawFacesSolid(dm, GPU_enable_material);
|
||||
if(ob->sculpt) {
|
||||
float planes[4][4];
|
||||
float (*fpl)[4] = NULL;
|
||||
|
||||
if(ob->sculpt->partial_redraw) {
|
||||
sculpt_get_redraw_planes(planes, ar, rv3d, ob);
|
||||
fpl = planes;
|
||||
ob->sculpt->partial_redraw = 0;
|
||||
}
|
||||
|
||||
dm->drawFacesSolid(dm, ob->sculpt->tree, fpl, GPU_enable_material);
|
||||
}
|
||||
else
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
|
||||
GPU_disable_material();
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
@@ -2802,7 +2817,8 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
} else {
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
dm->drawLooseEdges(dm);
|
||||
if(!ob->sculpt)
|
||||
dm->drawLooseEdges(dm);
|
||||
}
|
||||
else if(dt==OB_SHADED) {
|
||||
int do_draw= 1; /* to resolve all G.f settings below... */
|
||||
@@ -2920,7 +2936,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
}
|
||||
|
||||
/* returns 1 if nothing was drawn, for detecting to draw an object center */
|
||||
static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
|
||||
static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
Object *obedit= scene->obedit;
|
||||
@@ -2970,7 +2986,7 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
|
||||
(check_alpha)? &do_alpha_pass: NULL);
|
||||
}
|
||||
|
||||
draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
|
||||
draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
|
||||
|
||||
GPU_end_object_materials();
|
||||
|
||||
@@ -5566,7 +5582,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
|
||||
|
||||
switch( ob->type) {
|
||||
case OB_MESH:
|
||||
empty_object= draw_mesh_object(scene, v3d, rv3d, base, dt, flag);
|
||||
empty_object= draw_mesh_object(scene, ar, v3d, rv3d, base, dt, flag);
|
||||
if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
|
||||
|
||||
break;
|
||||
@@ -6260,7 +6276,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
if(dm) {
|
||||
dm->drawFacesSolid(dm, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
GPU_end_object_materials();
|
||||
}
|
||||
else if(edm)
|
||||
|
||||
@@ -1642,37 +1642,6 @@ void view3d_update_depths(ARegion *ar, View3D *v3d)
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
|
||||
static void draw_sculpt_depths(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
Object *ob = OBACT;
|
||||
|
||||
int dt= MIN2(v3d->drawtype, ob->dt);
|
||||
if(v3d->zbuf==0 && dt>OB_WIRE)
|
||||
dt= OB_WIRE;
|
||||
if(dt == OB_WIRE) {
|
||||
GLboolean depth_on;
|
||||
int orig_vdt = v3d->drawtype;
|
||||
int orig_zbuf = v3d->zbuf;
|
||||
int orig_odt = ob->dt;
|
||||
|
||||
glGetBooleanv(GL_DEPTH_TEST, &depth_on);
|
||||
v3d->drawtype = ob->dt = OB_SOLID;
|
||||
v3d->zbuf = 1;
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
draw_object(scene, ar, v3d, BASACT, 0);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
if(!depth_on)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
v3d->drawtype = orig_vdt;
|
||||
v3d->zbuf = orig_zbuf;
|
||||
ob->dt = orig_odt;
|
||||
}
|
||||
}
|
||||
|
||||
void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
|
||||
{
|
||||
RegionView3D *rv3d= ar->regiondata;
|
||||
@@ -2038,7 +2007,7 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
|
||||
}
|
||||
|
||||
// retopo= retopo_mesh_check() || retopo_curve_check();
|
||||
sculptparticle= (obact && obact->mode & (OB_MODE_SCULPT|OB_MODE_PARTICLE_EDIT)) && !scene->obedit;
|
||||
sculptparticle= (obact && obact->mode & (OB_MODE_PARTICLE_EDIT)) && !scene->obedit;
|
||||
if(retopo)
|
||||
view3d_update_depths(ar, v3d);
|
||||
|
||||
@@ -2051,8 +2020,6 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
|
||||
}
|
||||
|
||||
if(!retopo && sculptparticle && !(obact && (obact->dtx & OB_DRAWXRAY))) {
|
||||
if(obact && obact->mode & OB_MODE_SCULPT)
|
||||
draw_sculpt_depths(scene, ar, v3d);
|
||||
view3d_update_depths(ar, v3d);
|
||||
}
|
||||
|
||||
@@ -2067,8 +2034,6 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
|
||||
view3d_draw_xray(scene, ar, v3d, 1); // clears zbuffer if it is used!
|
||||
|
||||
if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) {
|
||||
if(obact && obact->mode & OB_MODE_SCULPT)
|
||||
draw_sculpt_depths(scene, ar, v3d);
|
||||
view3d_update_depths(ar, v3d);
|
||||
}
|
||||
|
||||
@@ -2090,8 +2055,6 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
|
||||
|
||||
ED_region_pixelspace(ar);
|
||||
|
||||
/* Draw Sculpt Mode brush XXX (removed) */
|
||||
|
||||
// retopo_paint_view_update(v3d);
|
||||
// retopo_draw_paint_lines();
|
||||
|
||||
|
||||
@@ -1802,12 +1802,9 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
|
||||
static int view3d_clipping_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
RegionView3D *rv3d= CTX_wm_region_view3d(C);
|
||||
ViewContext vc;
|
||||
bglMats mats;
|
||||
rcti rect;
|
||||
double mvmatrix[16];
|
||||
double projmatrix[16];
|
||||
double xs, ys, p[3];
|
||||
GLint viewport[4];
|
||||
short val;
|
||||
|
||||
rect.xmin= RNA_int_get(op->ptr, "xmin");
|
||||
rect.ymin= RNA_int_get(op->ptr, "ymin");
|
||||
@@ -1820,44 +1817,10 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
|
||||
/* note; otherwise opengl won't work */
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
||||
/* Get the matrices needed for gluUnProject */
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
|
||||
view3d_set_viewcontext(C, &vc);
|
||||
view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
|
||||
view3d_calculate_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect);
|
||||
|
||||
/* near zero floating point values can give issues with gluUnProject
|
||||
in side view on some implementations */
|
||||
if(fabs(mvmatrix[0]) < 1e-6) mvmatrix[0]= 0.0;
|
||||
if(fabs(mvmatrix[5]) < 1e-6) mvmatrix[5]= 0.0;
|
||||
|
||||
/* Set up viewport so that gluUnProject will give correct values */
|
||||
viewport[0] = 0;
|
||||
viewport[1] = 0;
|
||||
|
||||
/* four clipping planes and bounding volume */
|
||||
/* first do the bounding volume */
|
||||
for(val=0; val<4; val++) {
|
||||
|
||||
xs= (val==0||val==3)?rect.xmin:rect.xmax;
|
||||
ys= (val==0||val==1)?rect.ymin:rect.ymax;
|
||||
|
||||
gluUnProject(xs, ys, 0.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
|
||||
VECCOPY(rv3d->clipbb->vec[val], p);
|
||||
|
||||
gluUnProject(xs, ys, 1.0, mvmatrix, projmatrix, viewport, &p[0], &p[1], &p[2]);
|
||||
VECCOPY(rv3d->clipbb->vec[4+val], p);
|
||||
}
|
||||
|
||||
/* then plane equations */
|
||||
for(val=0; val<4; val++) {
|
||||
|
||||
CalcNormFloat(rv3d->clipbb->vec[val], rv3d->clipbb->vec[val==3?0:val+1], rv3d->clipbb->vec[val+4],
|
||||
rv3d->clip[val]);
|
||||
|
||||
rv3d->clip[val][3]= - rv3d->clip[val][0]*rv3d->clipbb->vec[val][0]
|
||||
- rv3d->clip[val][1]*rv3d->clipbb->vec[val][1]
|
||||
- rv3d->clip[val][2]*rv3d->clipbb->vec[val][2];
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,24 +124,24 @@ void view3d_get_view_aligned_coordinate(ViewContext *vc, float *fp, short mval[2
|
||||
}
|
||||
}
|
||||
|
||||
void view3d_get_transformation(ViewContext *vc, Object *ob, bglMats *mats)
|
||||
void view3d_get_transformation(ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats)
|
||||
{
|
||||
float cpy[4][4];
|
||||
int i, j;
|
||||
|
||||
Mat4MulMat4(cpy, ob->obmat, vc->rv3d->viewmat);
|
||||
Mat4MulMat4(cpy, ob->obmat, rv3d->viewmat);
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
for(j = 0; j < 4; ++j) {
|
||||
mats->projection[i*4+j] = vc->rv3d->winmat[i][j];
|
||||
mats->projection[i*4+j] = rv3d->winmat[i][j];
|
||||
mats->modelview[i*4+j] = cpy[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
mats->viewport[0] = vc->ar->winrct.xmin;
|
||||
mats->viewport[1] = vc->ar->winrct.ymin;
|
||||
mats->viewport[2] = vc->ar->winx;
|
||||
mats->viewport[3] = vc->ar->winy;
|
||||
mats->viewport[0] = ar->winrct.xmin;
|
||||
mats->viewport[1] = ar->winrct.ymin;
|
||||
mats->viewport[2] = ar->winx;
|
||||
mats->viewport[3] = ar->winy;
|
||||
}
|
||||
|
||||
/* ********************** view3d_select: selection manipulations ********************* */
|
||||
|
||||
@@ -481,6 +481,45 @@ void VIEW3D_OT_setobjectascamera(wmOperatorType *ot)
|
||||
}
|
||||
/* ********************************** */
|
||||
|
||||
void view3d_calculate_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, rcti *rect)
|
||||
{
|
||||
double xs, ys, p[3];
|
||||
short val;
|
||||
|
||||
/* near zero floating point values can give issues with gluUnProject
|
||||
in side view on some implementations */
|
||||
if(fabs(mats->modelview[0]) < 1e-6) mats->modelview[0]= 0.0;
|
||||
if(fabs(mats->modelview[5]) < 1e-6) mats->modelview[5]= 0.0;
|
||||
|
||||
/* Set up viewport so that gluUnProject will give correct values */
|
||||
mats->viewport[0] = 0;
|
||||
mats->viewport[1] = 0;
|
||||
|
||||
/* four clipping planes and bounding volume */
|
||||
/* first do the bounding volume */
|
||||
for(val=0; val<4; val++) {
|
||||
xs= (val==0||val==3)?rect->xmin:rect->xmax;
|
||||
ys= (val==0||val==1)?rect->ymin:rect->ymax;
|
||||
|
||||
gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
|
||||
VECCOPY(bb->vec[val], p);
|
||||
|
||||
gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
|
||||
VECCOPY(bb->vec[4+val], p);
|
||||
}
|
||||
|
||||
/* then plane equations */
|
||||
for(val=0; val<4; val++) {
|
||||
|
||||
CalcNormFloat(bb->vec[val], bb->vec[val==3?0:val+1], bb->vec[val+4],
|
||||
planes[val]);
|
||||
|
||||
planes[val][3]= - planes[val][0]*bb->vec[val][0]
|
||||
- planes[val][1]*bb->vec[val][1]
|
||||
- planes[val][2]*bb->vec[val][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* create intersection coordinates in view Z direction at mouse coordinates */
|
||||
void viewline(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float ray_end[3])
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#endif
|
||||
|
||||
struct DerivedMesh;
|
||||
struct GHash;
|
||||
|
||||
/* V - vertex, N - normal, T - uv, C - color
|
||||
F - float, UB - unsigned byte */
|
||||
@@ -124,6 +125,16 @@ void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool );
|
||||
GPUDrawObject *GPU_drawobject_new( struct DerivedMesh *dm );
|
||||
void GPU_drawobject_free( struct DerivedMesh *dm );
|
||||
|
||||
/* Buffers for non-DerivedMesh drawing */
|
||||
void *GPU_build_buffers(struct GHash *map, struct MVert *mvert,
|
||||
struct MFace *mface, int *face_indices,
|
||||
int totface, int *vert_indices, int uniq_verts,
|
||||
int totvert);
|
||||
void GPU_draw_buffers(void *buffers);
|
||||
void GPU_update_buffers(void *buffers, struct MVert *mvert,
|
||||
int *vert_indices, int totvert);
|
||||
void GPU_free_buffers(void *buffers);
|
||||
|
||||
/* called before drawing */
|
||||
void GPU_vertex_setup( struct DerivedMesh *dm );
|
||||
void GPU_normal_setup( struct DerivedMesh *dm );
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
@@ -376,6 +377,156 @@ void GPU_drawobject_free( DerivedMesh *dm )
|
||||
dm->drawObject = 0;
|
||||
}
|
||||
|
||||
/* Convenience struct for building the VBO.
|
||||
TODO: check that (lack-of) padding is OK,
|
||||
also check performance of short vs float for normals */
|
||||
typedef struct {
|
||||
float co[3];
|
||||
short no[3];
|
||||
|
||||
char pad[14];
|
||||
} VertexBufferFormat;
|
||||
|
||||
typedef struct {
|
||||
unsigned int vert_buf, tri_buf;
|
||||
unsigned short tot_tri;
|
||||
} GPU_Buffers;
|
||||
|
||||
void GPU_update_buffers2(void *buffers_v, MVert *mvert,
|
||||
int *vert_indices, int totvert)
|
||||
{
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
VertexBufferFormat *vert_data;
|
||||
int i;
|
||||
|
||||
vert_data = MEM_callocN(sizeof(VertexBufferFormat) * totvert, "bad");
|
||||
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
MVert *v = mvert + vert_indices[i];
|
||||
VertexBufferFormat *out = vert_data + i;
|
||||
|
||||
VecCopyf(out->co, v->co);
|
||||
memcpy(out->no, v->no, sizeof(short) * 3);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers->vert_buf);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(VertexBufferFormat) * totvert,
|
||||
vert_data, GL_STATIC_DRAW);
|
||||
|
||||
MEM_freeN(vert_data);
|
||||
}
|
||||
|
||||
void GPU_update_buffers(void *buffers_v, MVert *mvert,
|
||||
int *vert_indices, int totvert)
|
||||
{
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
VertexBufferFormat *vert_data;
|
||||
int i;
|
||||
|
||||
/* Build VBO */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers->vert_buf);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(VertexBufferFormat) * totvert,
|
||||
NULL, GL_STATIC_DRAW);
|
||||
vert_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
MVert *v = mvert + vert_indices[i];
|
||||
VertexBufferFormat *out = vert_data + i;
|
||||
|
||||
VecCopyf(out->co, v->co);
|
||||
memcpy(out->no, v->no, sizeof(short) * 3);
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
//printf("node updated %p\n", buffers_v);
|
||||
}
|
||||
|
||||
void *GPU_build_buffers(GHash *map, MVert *mvert, MFace *mface,
|
||||
int *face_indices, int totface,
|
||||
int *vert_indices, int tot_uniq_verts,
|
||||
int totvert)
|
||||
{
|
||||
GPU_Buffers *buffers;
|
||||
unsigned short *tri_data;
|
||||
int i, j, k, tottri;
|
||||
|
||||
buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
|
||||
|
||||
/* Count the number of triangles */
|
||||
for(i = 0, tottri = 0; i < totface; ++i)
|
||||
tottri += mface[face_indices[i]].v4 ? 2 : 1;
|
||||
|
||||
/* Generate index buffer object */
|
||||
glGenBuffers(1, &buffers->tri_buf);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers->tri_buf);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW);
|
||||
|
||||
/* Fill the triangle buffer */
|
||||
tri_data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = mface + face_indices[i];
|
||||
int v[3] = {f->v1, f->v2, f->v3};
|
||||
|
||||
for(j = 0; j < (f->v4 ? 2 : 1); ++j) {
|
||||
for(k = 0; k < 3; ++k) {
|
||||
void *value, *key = SET_INT_IN_POINTER(v[k]);
|
||||
int vbo_index;
|
||||
|
||||
value = BLI_ghash_lookup(map, key);
|
||||
vbo_index = GET_INT_FROM_POINTER(value);
|
||||
|
||||
if(vbo_index < 0) {
|
||||
vbo_index = -vbo_index +
|
||||
tot_uniq_verts - 1;
|
||||
}
|
||||
|
||||
*tri_data = vbo_index;
|
||||
++tri_data;
|
||||
}
|
||||
v[0] = f->v4;
|
||||
v[1] = f->v1;
|
||||
v[2] = f->v3;
|
||||
}
|
||||
}
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
||||
/* Build VBO */
|
||||
glGenBuffers(1, &buffers->vert_buf);
|
||||
GPU_update_buffers(buffers, mvert, vert_indices, totvert);
|
||||
|
||||
buffers->tot_tri = tottri;
|
||||
|
||||
return buffers;
|
||||
}
|
||||
|
||||
void GPU_draw_buffers(void *buffers_v)
|
||||
{
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers->vert_buf);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers->tri_buf);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), 0);
|
||||
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void*)12);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
void GPU_free_buffers(void *buffers_v)
|
||||
{
|
||||
if(buffers_v) {
|
||||
GPU_Buffers *buffers = buffers_v;
|
||||
|
||||
glDeleteBuffers(1, &buffers->vert_buf);
|
||||
glDeleteBuffers(1, &buffers->tri_buf);
|
||||
|
||||
MEM_freeN(buffers);
|
||||
}
|
||||
}
|
||||
|
||||
GPUBuffer *GPU_buffer_setup( DerivedMesh *dm, GPUDrawObject *object, int size, GLenum target, void *user, void (*copy_f)(DerivedMesh *, float *, int *, int *, void *) )
|
||||
{
|
||||
GPUBuffer *buffer;
|
||||
|
||||
Reference in New Issue
Block a user