- support for fake verse edges (subsurf modifier should work now)

- edges are generated from verse faces
   - no support for lose edge!
   - informations about edges aren't sent to verse server (other applications
     can't share edges with blender)
- better sending/receiving vertex position
This commit is contained in:
Jiri Hnidek 2007-04-27 14:04:30 +00:00
parent d584c8a1e6
commit 76c11ec9f7
5 changed files with 473 additions and 120 deletions

@ -37,6 +37,13 @@
#include "verse_ms.h"
struct VNode;
struct VerseEdge;
/*
* Verse Edge Hash (similar to edit edge hash)
*/
#define VEDHASHSIZE (512*512)
#define VEDHASH(a, b) ((a<b ? a : b) % VEDHASHSIZE)
/*
* virtual data type (used only for retype)
@ -118,7 +125,7 @@ typedef struct VerseVert {
real32 co[3]; /* x,y,z-coordinates of vertex */
real32 no[3]; /* normal of vertex */
/* blender internals */
short flag; /* flags: VERT_DELETED, VERT_RECEIVED */
short flag; /* flags: VERT_DELETED, VERT_RECEIVED, etc. */
void *vertex; /* pointer at EditVert or MVert */
int counter; /* counter of VerseFaces using this VerseVert */
union {
@ -127,8 +134,30 @@ typedef struct VerseVert {
} tmp; /* pointer at new created verse vert, it is
* used during duplicating geometry node */
float *cos; /* modified coordinates of vertex */
float *nos; /* modified normal vector */
} VerseVert;
/*
* structture used for verse edge hash
*/
typedef struct HashVerseEdge {
struct VerseEdge *vedge;
struct HashVerseEdge *next;
} HashVerseEdge;
/*
* fake verse data: edge
*/
typedef struct VerseEdge {
struct VerseEdge *next, *prev;
uint32 v0, v1; /* indexes of verse vertexes */
int counter; /* counter of verse faces using this edge */
struct HashVerseEdge hash; /* hash table */
union {
unsigned int index; /* temporary index of edge */
} tmp;
} VerseEdge;
/*
* verse data: polygon
*/
@ -147,6 +176,7 @@ typedef struct VerseFace {
short counter; /* counter of missed VerseVertexes */
void *face; /* pointer at EditFace */
float no[3]; /* normal vector */
float *nos; /* modified normal vector */
} VerseFace;
/*
@ -237,6 +267,8 @@ typedef struct VGeomData {
struct ListBase queue; /* queue of our layers waiting for receiving from verse server */
void *mesh; /* pointer at Mesh (object node) */
void *editmesh; /* pointer at EditMesh (edit mode) */
struct HashVerseEdge *hash; /* verse edge hash */
struct ListBase edges; /* list of fake verse edges */
/* client dependent methods */
void (*post_vertex_create)(struct VerseVert *vvert);
void (*post_vertex_set_xyz)(struct VerseVert *vvert);

@ -1019,7 +1019,8 @@ typedef struct {
struct VNode *vnode;
struct VLayer *vertex_layer;
struct VLayer *polygon_layer;
float (*verts)[3];
struct ListBase *edges;
float (*vertexCos)[3];
} VDerivedMesh;
/* this function set up border points of verse mesh bounding box */
@ -1034,7 +1035,7 @@ static void vDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
if(vdm->vertex_layer->dl.da.count > 0) {
while(vvert) {
DO_MINMAX(vdm->verts ? vvert->cos : vvert->co, min_r, max_r);
DO_MINMAX(vdm->vertexCos ? vvert->cos : vvert->co, min_r, max_r);
vvert = vvert->next;
}
}
@ -1055,7 +1056,9 @@ static int vDM_getNumVerts(DerivedMesh *dm)
/* this function return number of 'fake' edges */
static int vDM_getNumEdges(DerivedMesh *dm)
{
return 0;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
return BLI_countlist(vdm->edges);
}
/* this function returns number of polygons in polygon layer */
@ -1071,10 +1074,13 @@ static int vDM_getNumFaces(DerivedMesh *dm)
* but it return 'indexth' vertex of dynamic list */
void vDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
{
VerseVert *vvert = ((VDerivedMesh*)dm)->vertex_layer->dl.lb.first;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseVert *vvert;
int i;
for(i=0 ; i<index; i++) vvert = vvert->next;
if(!vdm->vertex_layer) return;
for(vvert = vdm->vertex_layer->dl.lb.first, i=0 ; i<index; i++) vvert = vvert->next;
if(vvert) {
VECCOPY(vert_r->co, vvert->co);
@ -1089,25 +1095,59 @@ void vDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
}
}
/* dummy function, because verse mesh doesn't store edges */
/* this function returns fake verse edge */
void vDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
{
edge_r->flag = 0;
edge_r->crease = 0;
edge_r->v1 = 0;
edge_r->v2 = 0;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseEdge *vedge;
struct VLayer *vert_vlayer = vdm->vertex_layer;
struct VerseVert *vvert;
int j;
if(!vdm->vertex_layer || !vdm->edges) return;
if(vdm->edges->first) {
struct VerseVert *vvert1, *vvert2;
/* store vert indices in tmp union */
for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, j++)
vvert->tmp.index = j;
for(vedge = vdm->edges->first; vedge; vedge = vedge->next) {
if(vedge->tmp.index==index) {
vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
if(vvert1 && vvert2) {
edge_r->v1 = vvert1->tmp.index;
edge_r->v2 = vvert2->tmp.index;
}
else {
edge_r->v1 = 0;
edge_r->v2 = 0;
}
/* not supported yet */
edge_r->flag = 0;
edge_r->crease = 0;
break;
}
}
}
}
/* this function doesn't return face with index of access array,
* but it returns 'indexth' vertex of dynamic list */
void vDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
{
struct VerseFace *vface = ((VDerivedMesh*)dm)->polygon_layer->dl.lb.first;
struct VerseVert *vvert = ((VDerivedMesh*)dm)->vertex_layer->dl.lb.first;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseFace *vface;
struct VerseVert *vvert;
struct VerseVert *vvert0, *vvert1, *vvert2, *vvert3;
int i;
for(i = 0; i < index; ++i) vface = vface->next;
if(!vdm->vertex_layer || !vdm->polygon_layer) return;
for(vface = vdm->polygon_layer->dl.lb.first, i = 0; i < index; ++i) vface = vface->next;
face_r->mat_nr = 0;
face_r->flag = 0;
@ -1119,7 +1159,7 @@ void vDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
vvert3 = vface->vvert3;
if(!vvert3) face_r->v4 = 0;
for(i = 0; vvert0 || vvert1 || vvert2 || vvert3; i++, vvert = vvert->next) {
for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert0 || vvert1 || vvert2 || vvert3; i++, vvert = vvert->next) {
if(vvert == vvert0) {
face_r->v1 = i;
vvert0 = NULL;
@ -1144,9 +1184,12 @@ void vDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
/* fill array of mvert */
void vDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
{
VerseVert *vvert = ((VDerivedMesh *)dm)->vertex_layer->dl.lb.first;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseVert *vvert;
for( ; vvert; vvert = vvert->next, ++vert_r) {
if(!vdm->vertex_layer) return;
for(vvert = vdm->vertex_layer->dl.lb.first ; vvert; vvert = vvert->next, ++vert_r) {
VECCOPY(vert_r->co, vvert->co);
vert_r->no[0] = vvert->no[0] * 32767.0;
@ -1161,20 +1204,56 @@ void vDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
/* dummy function, edges arent supported in verse mesh */
void vDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
if(!vdm->vertex_layer || !vdm->edges) return;
if(vdm->edges->first) {
struct VerseEdge *vedge;
struct VLayer *vert_vlayer = vdm->vertex_layer;
struct VerseVert *vvert, *vvert1, *vvert2;
int j;
/* store vert indices in tmp union */
for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, ++j)
vvert->tmp.index = j;
for(vedge = vdm->edges->first, j=0 ; vedge; vedge = vedge->next, ++edge_r, j++) {
/* create temporary edge index */
vedge->tmp.index = j;
vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
if(vvert1 && vvert2) {
edge_r->v1 = vvert1->tmp.index;
edge_r->v2 = vvert2->tmp.index;
}
else {
printf("error: vDM_copyEdgeArray: %d, %d\n", vedge->v0, vedge->v1);
edge_r->v1 = 0;
edge_r->v2 = 0;
}
/* not supported yet */
edge_r->flag = 0;
edge_r->crease = 0;
}
}
}
/* fill array of mfaces */
void vDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
{
VerseFace *vface = ((VDerivedMesh*)dm)->polygon_layer->dl.lb.first;
VerseVert *vvert = ((VDerivedMesh*)dm)->vertex_layer->dl.lb.first;
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseFace *vface;
struct VerseVert *vvert;
int i;
if(!vdm->vertex_layer || !vdm->polygon_layer) return;
/* store vertexes indices in tmp union */
for(i = 0; vvert; vvert = vvert->next, ++i)
for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert; vvert = vvert->next, ++i)
vvert->tmp.index = i;
for( ; vface; vface = vface->next, ++face_r) {
for(vface = vdm->polygon_layer->dl.lb.first; vface; vface = vface->next, ++face_r) {
face_r->mat_nr = 0;
face_r->flag = 0;
@ -1188,8 +1267,7 @@ void vDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
}
}
/* return coordination of vertex with index ... I suppose, that it will
* be very hard to do, becuase there can be holes in access array */
/* return coordination of vertex with index */
static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
@ -1198,8 +1276,9 @@ static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
if(!vdm->vertex_layer) return;
vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
if(vvert) {
VECCOPY(co_r, vdm->verts ? vvert->cos : vvert->co);
VECCOPY(co_r, vdm->vertexCos ? vvert->cos : vvert->co);
}
else {
co_r[0] = co_r[1] = co_r[2] = 0.0;
@ -1217,14 +1296,13 @@ static void vDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
vvert = vdm->vertex_layer->dl.lb.first;
while(vvert) {
VECCOPY(cos_r[i], vdm->verts ? vvert->cos : vvert->co);
VECCOPY(cos_r[i], vdm->vertexCos ? vvert->cos : vvert->co);
i++;
vvert = vvert->next;
}
}
/* return normal of vertex with index ... again, it will be hard to
* implemente, because access array */
/* return normal of vertex with index */
static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
@ -1253,7 +1331,7 @@ static void vDM_drawVerts(DerivedMesh *dm)
bglBegin(GL_POINTS);
while(vvert) {
bglVertex3fv(vdm->verts ? vvert->cos : vvert->co);
bglVertex3fv(vdm->vertexCos ? vvert->cos : vvert->co);
vvert = vvert->next;
}
bglEnd();
@ -1265,21 +1343,22 @@ static void vDM_drawVerts(DerivedMesh *dm)
static void vDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseFace *vface;
struct VerseEdge *vedge;
struct VLayer *vert_vlayer = vdm->vertex_layer;
if(!vdm->polygon_layer) return;
if(vert_vlayer && vdm->edges && (BLI_countlist(vdm->edges) > 0)) {
struct VerseVert *vvert1, *vvert2;
vface = vdm->polygon_layer->dl.lb.first;
while(vface) {
glBegin(GL_LINE_LOOP);
glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3) glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
glBegin(GL_LINES);
for(vedge = vdm->edges->first; vedge; vedge = vedge->next) {
vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
if(vvert1 && vvert2) {
glVertex3fv(vdm->vertexCos ? vvert1->cos : vvert1->co);
glVertex3fv(vdm->vertexCos ? vvert2->cos : vvert2->co);
}
}
glEnd();
vface = vface->next;
}
}
@ -1303,40 +1382,21 @@ static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
vface = vdm->polygon_layer->dl.lb.first;
glShadeModel(GL_FLAT);
while(vface) {
/* if((vface->smooth) && (vface->smooth->value)){
glShadeModel(GL_SMOOTH);
glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
glNormal3fv(vface->vvert0->no);
glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
glNormal3fv(vface->vvert1->no);
glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
glNormal3fv(vface->vvert2->no);
glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3){
glNormal3fv(vface->vvert3->no);
glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
}
glEnd();
}
else { */
glShadeModel(GL_FLAT);
glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
glNormal3fv(vface->no);
glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3)
glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
glEnd();
/* } */
glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
glNormal3fv(vface->no);
glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3)
glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
glEnd();
vface = vface->next;
}
glShadeModel(GL_FLAT);
}
/* thsi function should draw mesh with mapped texture, but it isn't supported yet */
/* this function should draw mesh with mapped texture, but it isn't supported yet */
static void vDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
@ -1348,11 +1408,11 @@ static void vDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tfac
while(vface) {
glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3)
glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
glEnd();
vface = vface->next;
@ -1372,11 +1432,11 @@ static void vDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char
while(vface) {
glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
if(vface->vvert3)
glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
glEnd();
vface = vface->next;
@ -1447,7 +1507,7 @@ static void vDM_release(DerivedMesh *dm)
VDerivedMesh *vdm = (VDerivedMesh*)dm;
if (DM_release(dm)) {
if(vdm->verts) MEM_freeN(vdm->verts);
if(vdm->vertexCos) MEM_freeN(vdm->vertexCos);
MEM_freeN(vdm);
}
}
@ -1462,9 +1522,11 @@ DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3])
vdm->vnode = vnode;
vdm->vertex_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
vdm->polygon_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
vdm->edges = &((VGeomData*)vnode->data)->edges;
/* vertex and polygon layer has to exist */
if(vdm->vertex_layer && vdm->polygon_layer)
DM_init(&vdm->dm, vdm->vertex_layer->dl.da.count, 0, vdm->polygon_layer->dl.da.count);
DM_init(&vdm->dm, vdm->vertex_layer->dl.da.count, BLI_countlist(vdm->edges), vdm->polygon_layer->dl.da.count);
else
DM_init(&vdm->dm, 0, 0, 0);
@ -1506,28 +1568,7 @@ DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3])
vdm->dm.release = vDM_release;
if(vdm->vertex_layer) {
if(vertexCos) {
int i;
vdm->verts = MEM_mallocN(sizeof(float)*3*vdm->vertex_layer->dl.da.count, "verse mod vertexes");
vvert = vdm->vertex_layer->dl.lb.first;
for(i=0; i<vdm->vertex_layer->dl.da.count && vvert; i++, vvert = vvert->next) {
VECCOPY(vdm->verts[i], vertexCos[i]);
vvert->cos = vdm->verts[i];
}
}
else {
vdm->verts = NULL;
vvert = vdm->vertex_layer->dl.lb.first;
while(vvert) {
vvert->cos = NULL;
vvert = vvert->next;
}
}
}
vdm->vertexCos = vertexCos;
return (DerivedMesh*) vdm;
}

@ -400,10 +400,12 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
if(index) {
orig = *index++;
if(orig == ORIGINDEX_NONE) continue;
flag = drawParamsMapped(userData, orig);
if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
else continue;
}
else
flag = drawParamsMapped(userData, i);
if(drawParamsMapped) flag = drawParamsMapped(userData, i);
else continue;
}
if(flag == 0)

@ -78,6 +78,16 @@ static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer
static void increase_verse_verts_references(struct VerseFace *vface);
static void recalculate_verseface_normals(struct VNode *vnode);
/* verse edge functions */
static VerseEdge* find_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
static void insert_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge);
static void remove_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge);
static void remove_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
static void add_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
static void update_edgehash_of_deleted_verseface(struct VNode *vnode, struct VerseFace *vface);
static void update_edgehash_of_changed_verseface(struct VNode *vnode, struct VerseFace *vface, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
static void update_edgehash_of_new_verseface(struct VNode *vnode, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
/*
* recalcute normals of all VerseFaces
*/
@ -799,6 +809,22 @@ VerseVert* create_verse_vertex(
return vvert;
}
/*
* this function creates fake VerseEdge and returns pointer at this edge
*/
VerseEdge *create_verse_edge(uint32 v0, uint32 v1)
{
struct VerseEdge *vedge;
vedge = (VerseEdge*)MEM_mallocN(sizeof(VerseEdge), "VerseEdge");
vedge->v0 = v0;
vedge->v1 = v1;
vedge->counter = 0;
return vedge;
}
/*
* this function will create new VerseFace and will return pointer on such Face
*/
@ -903,6 +929,10 @@ VGeomData *create_geometry_data(void)
geom->mesh = NULL;
geom->editmesh = NULL;
/* initialize list of fake verse edges and initialize verse edge hash */
geom->edges.first = geom->edges.last = NULL;
geom->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
/* set up methods */
geom->post_vertex_create = post_vertex_create;
geom->post_vertex_set_xyz = post_vertex_set_xyz;
@ -1058,6 +1088,9 @@ static void cb_g_polygon_delete(
vface = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
if(!vface) return;
/* update edge hash */
update_edgehash_of_deleted_verseface(vnode, vface);
((VGeomData*)vnode->data)->post_polygon_delete(vface);
@ -1106,6 +1139,231 @@ static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id)
return NULL;
}
/*
* this function will find edge in hash table, hash function isn't too optimal (it needs
* lot of memory for every verse node), but it works without any bug
*/
static VerseEdge* find_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
{
struct HashVerseEdge *hve;
if(((VGeomData*)vnode->data)->hash==NULL)
((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
hve = ((VGeomData*)vnode->data)->hash + VEDHASH(v0, v1);;
while(hve) {
/* edge v0---v1 is the same edge as v1---v0 */
if(hve->vedge && ((hve->vedge->v0==v0 && hve->vedge->v1==v1) || (hve->vedge->v0==v1 && hve->vedge->v1==v0))) return hve->vedge;
hve = hve->next;
}
return NULL;
}
/*
* insert hash of verse edge to hash table
*/
static void insert_verse_edgehash(VNode *vnode, VerseEdge *vedge)
{
struct HashVerseEdge *first, *hve;
if(((VGeomData*)vnode->data)->hash==NULL)
((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1);
if(first->vedge==NULL) {
first->vedge = vedge;
}
else {
hve = &(vedge->hash);
hve->vedge = vedge;
hve->next = first->next;
first->next = hve;
}
}
/*
* remove hash of verse edge from hash table
*/
static void remove_verse_edgehash(VNode *vnode, VerseEdge *vedge)
{
struct HashVerseEdge *first, *hve, *prev;
hve = first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1);
while(hve) {
if(hve->vedge == vedge) {
if(hve==first) {
if(first->next) {
hve = first->next;
first->vedge = hve->vedge;
first->next = hve->next;
}
else {
hve->vedge = NULL;
}
}
else {
prev->next = hve->next;
}
return;
}
prev = hve;
hve = hve->next;
}
}
/*
* this function will try to remove existing fake verse edge, when this verse
* edge is still used by some faces, then counter will be only decremented
*/
static void remove_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
{
struct VerseEdge *vedge;
vedge = find_verse_edge(vnode, v0, v1);
if(vedge) {
vedge->counter--;
if(vedge->counter==0) {
remove_verse_edgehash(vnode, vedge);
BLI_freelinkN(&(((VGeomData*)vnode->data)->edges), vedge);
}
}
else {
printf("error: remove_verse_edge %d, %d\n", v0, v1);
}
}
/*
* this function will try to add new fake verse edge, when no such edge exist,
* when such edge exist, then only counter of edge will be incremented
*/
static void add_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
{
struct VerseEdge *vedge;
vedge = find_verse_edge(vnode, v0, v1);
if(!vedge) {
if(v0!=v1) {
vedge = create_verse_edge(v0, v1);
BLI_addtail(&(((VGeomData*)vnode->data)->edges), vedge);
insert_verse_edgehash(vnode, vedge);
}
else {
printf("error:add_verse_edge: %d, %d\n", v0, v1);
return;
}
}
vedge->counter++;
}
/*
* verse face was deleted ... update edge hash
*/
static void update_edgehash_of_deleted_verseface(VNode *vnode, VerseFace *vface)
{
uint32 v0, v1, v2, v3; /* verse vertex indexes of deleted verse face */
v0 = vface->vvert0->id;
v1 = vface->vvert1->id;
v2 = vface->vvert2->id;
v3 = vface->vvert3 ? vface->vvert3->id : -1;
remove_verse_edge(vnode, v0, v1);
remove_verse_edge(vnode, v1, v2);
if(v3!=-1) {
remove_verse_edge(vnode, v2, v3);
remove_verse_edge(vnode, v3, v0);
}
else {
remove_verse_edge(vnode, v2, v0);
}
}
/*
* existing verse face was changed ... update edge hash
*/
static void update_edgehash_of_changed_verseface(
VNode *vnode,
VerseFace *vface,
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
uint32 ov0, ov1, ov2, ov3; /* old indexes at verse vertexes*/
ov0 = vface->vvert0->id;
ov1 = vface->vvert1->id;
ov2 = vface->vvert2->id;
ov3 = vface->vvert3 ? vface->vvert3->id : -1;
/* 1st edge */
if(v0!=ov0 || v1!=ov1) {
remove_verse_edge(vnode, ov0, ov1);
add_verse_edge(vnode, v0, v1);
}
/* 2nd edge */
if(v1!=ov1 || v2!=ov2) {
remove_verse_edge(vnode, ov1, ov2);
add_verse_edge(vnode, v1, v2);
}
/* 3rd edge */
if(v2!=ov2 || v3!=ov3 || v0!=ov0) {
if(ov3!=-1) {
remove_verse_edge(vnode, ov2, ov3);
if(v3!=-1) {
add_verse_edge(vnode, v2, v3); /* new 3rd edge (quat->quat) */
}
else {
remove_verse_edge(vnode, ov3, ov0); /* old edge v3,v0 of quat have to be removed */
add_verse_edge(vnode, v2, v0); /* new 3rd edge (quat->triangle) */
}
}
else {
remove_verse_edge(vnode, ov2, ov0);
if(v3!=-1) {
add_verse_edge(vnode, v2, v3); /* new 3rd edge (triangle->quat) */
}
else {
add_verse_edge(vnode, v2, v0); /* new 3rd edge (triangle->triangle) */
}
}
}
/* 4th edge */
if(v3!=-1 && (v3!=ov3 || v0!=ov0)) {
remove_verse_edge(vnode, ov3, ov0);
add_verse_edge(vnode, v3, v0);
}
}
/*
* new verse face was created ... update list of edges and edge has
*/
static void update_edgehash_of_new_verseface(
VNode *vnode,
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
/* when edge already exists, then only its counter is incremented,
* look at commentary of add_verse_edge() function */
add_verse_edge(vnode, v0, v1);
add_verse_edge(vnode, v1, v2);
if(v3!=-1) {
add_verse_edge(vnode, v2, v3);
add_verse_edge(vnode, v3, v0);
}
else {
add_verse_edge(vnode, v2, v0);
}
}
/*
* callback function: new polygon (face) created or existing polygon was changed
*/
@ -1166,6 +1424,9 @@ static void cb_g_polygon_set_corner_uint32(
* layer ids */
vface = find_verse_face_in_queue(vlayer, node_id, polygon_id, v0, v1, v2, v3);
/* update edge hash */
update_edgehash_of_new_verseface(vnode, v0, v1, v2, v3);
if(vface){
/* printf("\tremove from vface queue\n");*/
/* I creeated this face ... remove VerseFace from queue */
@ -1204,6 +1465,9 @@ static void cb_g_polygon_set_corner_uint32(
/* VerseVertexes of existing VerseFace were changed (VerseFace will use some different
* VerseVertexes or it will use them in different order) */
/* update fake verse edges */
update_edgehash_of_changed_verseface(vnode, vface, v0, v1, v2, v3);
/* initialize count of unreceived vertexes needed for this face */
vface->counter = 4;
@ -1423,19 +1687,24 @@ static void cb_g_vertex_set_xyz_real32(
if(vvert->flag & VERT_OBSOLETE) return;
if (vvert->flag & VERT_LOCKED) {
/* this application changed position of this vertex */
if((vvert->co[0]==x) && (vvert->co[1]==y) && (vvert->co[2]==z)) {
if (!(vvert->flag & VERT_POS_OBSOLETE))
vvert->flag &= ~VERT_LOCKED;
recalculate_verseface_normals(vnode);
((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
/* unlock vertex position */
vvert->flag &= ~VERT_LOCKED;
/* call post_vertex_set_xyz only, when position of vertex is
* obsolete ... the new vertex position will be sent to
* verse server */
if (vvert->flag & VERT_POS_OBSOLETE) {
((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
}
}
}
else {
/* somebody else changed position of this vertex*/
if((vvert->co[0]!=x) || (vvert->co[1]!=y) || (vvert->co[2]!=z)) {
vvert->co[0] = x;
vvert->co[1] = y;
vvert->co[2] = z;
recalculate_verseface_normals(vnode);
((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
}
@ -1625,6 +1894,10 @@ void free_geom_data(VNode *vnode)
((VGeomData*)vnode->data)->post_geometry_free_constraint(vnode);
/* free all VerseLayers */
BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
/* free fake verse edges */
BLI_freelistN(&((VGeomData*)vnode->data)->edges);
/* free edge hash */
MEM_freeN(((VGeomData*)vnode->data)->hash);
}
}

@ -467,38 +467,45 @@ void b_verse_send_vertex_delete(EditVert *eve)
*/
void send_versevert_pos(VerseVert *vvert)
{
/* delete command was sent to verse server ... sending one
* more position command would create new vertex */
if ((vvert->flag & VERT_DELETED) | (vvert->flag & VERT_OBSOLETE)) return;
/* don't send position of verse vertex to verse server, because it could create
* new vertex */
if(vvert->flag & VERT_RECEIVED && !(vvert->flag & VERT_DELETED)) {
if(vvert->flag & VERT_RECEIVED) {
if(vvert->flag & VERT_LOCKED) {
/* when position of verse vert was sent to verse server
* and it wasn't received yet, then mark sent position
* as obsolete ... blender will automaticaly send actual
* position, when old will be received */
vvert->flag |= VERT_POS_OBSOLETE;
/* printf("\tsend_versevert_pos: %d mark OBSOLETE\n", vvert->id);*/
}
else {
struct EditVert *eve = (EditVert*)vvert->vertex;
/* send position to verse server, when it is different from actual position */
if(eve && (eve->co[0]!=vvert->co[0] || eve->co[1]!=vvert->co[1] || eve->co[2]!=vvert->co[2])) {
/* lock vertex and send its position to verse server */
/* lock vertex and send its position to verse server,
* locking of vertex prevents from sending too many
* informations about vertex position during draging
* of vertex */
vvert->flag |= VERT_LOCKED;
VECCOPY(vvert->co, eve->co);
/* printf("\tsend_versevert_pos: %d send and LOCK \n", vvert->id);*/
send_verse_vertex(vvert);
}
}
}
if(!(vvert->flag & VERT_RECEIVED) && (vvert->flag & VERT_LOCKED)) {
else {
/* we created this vertex and we sent new position to verse server, but "confirmation" command about
* position of vertex didn't arrived yet, then we can't send new position of vertex ... we only mark
* position of vertex as obsolete and new position will be sent to verse server, when confirmation
* command will arive */
struct EditVert *eve = (EditVert*)vvert->vertex;
if(eve && (eve->co[0]!=vvert->co[0] || eve->co[1]!=vvert->co[1] || eve->co[2]!=vvert->co[2])) {
/* printf("\tsend_versevert_pos: %d mark VERT_POS_OBSOLETE\n", vvert->id); */
vvert->flag |= VERT_POS_OBSOLETE;
}
}
verse_callback_update(0);
}
@ -723,7 +730,6 @@ void post_vertex_set_xyz(VerseVert *vvert)
eve = (EditVert*)vvert->vertex;
VECCOPY(vvert->co, eve->co);
/* printf("\tpost_vertex_set_xyz: %d send and NOT_OBSOLETE\n", vvert->id); */
send_verse_vertex(vvert);
verse_callback_update(0);
}
@ -733,12 +739,11 @@ void post_vertex_set_xyz(VerseVert *vvert)
return;
}
/* when shared object is in edit mode, then update editmesh */
if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
if(vvert->vertex) {
eve = (EditVert*)vvert->vertex;
/* printf("\tupdate pos of edit vert %d\n", vvert->id); */
VECCOPY(eve->co, vvert->co);
recalc_editnormals();
}