diff --git a/source/blender/blenkernel/BKE_verse.h b/source/blender/blenkernel/BKE_verse.h index 18dfbf15640..fe5fc44ba1e 100644 --- a/source/blender/blenkernel/BKE_verse.h +++ b/source/blender/blenkernel/BKE_verse.h @@ -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) ((avertex_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 ; inext; + if(!vdm->vertex_layer) return; + + for(vvert = vdm->vertex_layer->dl.lb.first, i=0 ; inext; 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; ivertex_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; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 404e433d6cd..c983f6b48e5 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -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) diff --git a/source/blender/blenkernel/intern/verse_geometry_node.c b/source/blender/blenkernel/intern/verse_geometry_node.c index 9af22bfd37d..8d58d140c79 100644 --- a/source/blender/blenkernel/intern/verse_geometry_node.c +++ b/source/blender/blenkernel/intern/verse_geometry_node.c @@ -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); } } diff --git a/source/blender/src/verse_mesh.c b/source/blender/src/verse_mesh.c index 350d78b6bae..8c7d6509502 100644 --- a/source/blender/src/verse_mesh.c +++ b/source/blender/src/verse_mesh.c @@ -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(); }