Commit of the sculpt patch (#19672). Further development will be in this branch until we merge to trunk.

This commit is contained in:
2009-10-27 19:53:34 +00:00
parent b2c2dafb68
commit 93beb0b85a
25 changed files with 1485 additions and 480 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View 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);

View File

@@ -28,6 +28,7 @@ FILE(GLOB SRC intern/*.c)
SET(INC
. ../makesdna ../blenkernel ../../../intern/guardedalloc ../include
../gpu
${FREETYPE_INCLUDE_DIRS}
${ZLIB_INC}
)

View File

@@ -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 = ''

View File

@@ -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);

View 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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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

View File

@@ -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)

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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 ********************* */

View File

@@ -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])
{

View File

@@ -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 );

View File

@@ -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;