- support for fake verse edges (subsurf modifier should work now)
authorJiri Hnidek <jiri.hnidek@tul.cz>
Fri, 27 Apr 2007 14:04:30 +0000 (14:04 +0000)
committerJiri Hnidek <jiri.hnidek@tul.cz>
Fri, 27 Apr 2007 14:04:30 +0000 (14:04 +0000)
   - 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

source/blender/blenkernel/BKE_verse.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/verse_geometry_node.c
source/blender/src/verse_mesh.c

index 18dfbf1564006175fc05ac9f88712d705326455d..fe5fc44ba1e583ff44e1924307b6c904b1f9f81b 100644 (file)
 #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);
index ff704d59463f64abd1eb443018f498265621c8bf..38762d8f49aa6b13eb18a9c02e3ce5f08459a56c 100644 (file)
@@ -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;
+
+       if(!vdm->vertex_layer) return;
 
-       for( ; vvert; vvert = vvert->next, ++vert_r) {
+       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;
 }
index 404e433d6cd3a636c0f5cca9a20d1063e44afbfc..c983f6b48e535ac9bf8f106bd5091f50b57ff21e 100644 (file)
@@ -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)
index 9af22bfd37d446bd2517226408e052e81fd94d06..8d58d140c79a5d081a70726946fbe7cb6f356b99 100644 (file)
@@ -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);
        }
 }
 
index 350d78b6baeb13343268937798df4076100b7172..8c7d65095029a7de54977052fd01fa4b308f5ac9 100644 (file)
@@ -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();
                }