Files
test/source/blender/blenkernel/intern/verse_geometry_node.c
Joseph Eagar 30313645b0 Split dissolve_disk into dissolve_vert and dissolve_disk as agreed.
also made dissolve vert bmop use the error api, and put in some code 
to report it to the user in the xkey ui code.

Need to make a file in editors/mesh for client code utility functions for 
bmesh, like e.g. reporting bmesh errors to the user, handling conversion 
more automatically, etc.
2009-03-01 06:36:16 +00:00

2102 lines
57 KiB
C

/**
* $Id: verse_geometry_node.c 12931 2007-12-17 18:20:48Z theeth $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contributor(s): Jiri Hnidek.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifdef WITH_VERSE
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "BLI_dynamiclist.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BKE_verse.h"
#include "BKE_utildefines.h"
#include "BIF_verse.h"
#include "verse.h"
/* function prototypes of static functions */
/* test functions for callback functions */
static char test_polygon_set_corner_uint32(uint32 v0, uint32 v1, uint32 v2, uint32 v3);
/* callback functions */
static void cb_g_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real);
static void cb_g_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
static void cb_g_vertex_set_xyz_real32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 vertex_id, real32 x, real32 y, real32 z);
static void cb_g_polygon_set_corner_uint32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
static void cb_g_vertex_delete_real32(void *user_data, VNodeID node_id, uint32 vertex_id);
static void cb_g_polygon_delete(void *user_data, VNodeID node_id, uint32 polygon_id);
static void cb_g_crease_set_edge(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
static void cb_g_crease_set_vertex(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
/* other static functions */
static void free_unneeded_verseverts_of_verseface(struct VNode *vnode, struct VerseFace *vface);
static void free_verse_vertex(struct VLayer *vlayer, struct VerseVert *vvert);
static void free_verse_face(struct VLayer *vlayer, struct VerseFace *vface);
static void free_verse_layer_data(struct VNode *vnode, struct VLayer *vlayer);
static void send_verse_face(struct VerseFace *vface);
static VerseVert* find_verse_vert_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 vertex_id, real32 x, real32 y, real32 z);
static VerseFace* find_verse_face_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
static unsigned short test_incoming_verseface(struct VGeomData *geom, struct VerseFace *vface);
static void find_unsent_faces(struct VNode *vnode, struct VerseVert *vvert);
static void find_vlayer_orphans(struct VNode *vnode, struct VerseVert *vvert);
static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer, struct VerseFace *vface);
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
*/
static void recalculate_verseface_normals(VNode *vnode)
{
struct VLayer *vert_layer, *face_layer;
struct VerseFace *vface;
struct VerseVert *vvert;
if(vnode->type != V_NT_GEOMETRY) return;
vert_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
face_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
vvert = vert_layer->dl.lb.first;
while(vvert) {
vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
vvert = vvert->next;
}
vface = face_layer->dl.lb.first;
while(vface) {
/* calculate face normals */
if(vface->vvert3) {
CalcNormFloat4(vface->vvert0->co, vface->vvert1->co,
vface->vvert2->co, vface->vvert3->co, vface->no);
VecAddf(vface->vvert3->no, vface->vvert3->no, vface->no);
}
else
CalcNormFloat(vface->vvert0->co, vface->vvert1->co,
vface->vvert2->co, vface->no);
/* calculate vertex normals ... it is averadge of all face normals using the vertex */
VecAddf(vface->vvert0->no, vface->vvert0->no, vface->no);
VecAddf(vface->vvert1->no, vface->vvert1->no, vface->no);
VecAddf(vface->vvert2->no, vface->vvert2->no, vface->no);
vface = vface->next;
}
/* we have to normalize all vertex normals */
vvert = vert_layer->dl.lb.first;
while(vvert) {
Normalize(vvert->no);
vvert = vvert->next;
}
}
/*
* add created item to the queue and send it if possible
*/
void add_item_to_send_queue(ListBase *lb, void *item, short type)
{
struct VNode *vnode;
struct VLayer *vlayer;
struct VerseVert *vvert;
struct VerseFace *vface;
/* this prevent from adding duplicated faces */
if(type==VERSE_FACE) {
struct Link *link = (Link*)lb->first;
while(link) {
if(link==item) {
if(((VerseFace*)item)->flag & FACE_SENT) {
/* printf("\tverse face %d marked as OBSOLETE\n", ((VerseFace*)item)->id);*/
((VerseFace*)item)->flag |= FACE_OBSOLETE;
}
return;
}
link = link->next;
}
}
/* add item to sending queue (two way dynamic list) */
BLI_addtail(lb, item);
/* send item, when it is possible */
switch (type) {
case VERSE_NODE: /* only first node in queue can be sent */
if(lb->first==lb->last)
send_verse_node((VNode*)item);
break;
case VERSE_LINK: /* both object between have to exist */
if(((VLink*)item)->flag & LINK_SEND_READY)
send_verse_link((VLink*)item);
break;
case VERSE_LAYER:
if(((VLayer*)item)->vnode->flag & NODE_RECEIVED)
send_verse_layer((VLayer*)item);
break;
case VERSE_VERT:
if(((VerseVert*)item)->vlayer->flag & LAYER_RECEIVED)
send_verse_vertex((VerseVert*)item);
break;
case VERSE_FACE: /* all vertexes of face have to be received */
if(((VerseFace*)item)->flag & FACE_SEND_READY)
send_verse_face((VerseFace*)item);
break;
case VERSE_TAG:
send_verse_tag((VTag*)item);
break;
case VERSE_TAG_GROUP:
send_verse_taggroup((VTagGroup*)item);
break;
case VERSE_VERT_UINT32: /* parent item has to exist */
vnode = (((uint32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id );
if(vvert != NULL)
send_verse_vert_uint32((uint32_item*)item, type);
break;
case VERSE_VERT_REAL32: /* parent item has to exist */
vnode = (((real32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id );
if( vvert != NULL)
send_verse_vert_real32((real32_item*)item, type);
break;
case VERSE_VERT_VEC_REAL32: /* parent item has to exist */
vnode = (((vec_real32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((vec_real32_item*)item)->id );
if(vvert != NULL)
send_verse_vert_vec_real32((vec_real32_item*)item, type);
break;
case VERSE_FACE_UINT8: /* parent item has to exist */
vnode = (((uint8_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint8_item*)item)->id );
if(vface != NULL)
send_verse_face_uint8((uint8_item*)item, type);
break;
case VERSE_FACE_UINT32: /* parent item has to exist */
vnode = (((uint32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id );
if(vface != NULL)
send_verse_face_uint32((uint32_item*)item, type);
break;
case VERSE_FACE_REAL32: /* parent item has to exist */
vnode = (((real32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id );
if(vface != NULL)
send_verse_face_real32((real32_item*)item, type);
break;
case VERSE_FACE_QUAT_UINT32: /* parent item has to exist */
vnode = (((quat_uint32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_uint32_item*)item)->id );
if(vface != NULL)
send_verse_face_corner_quat_uint32((quat_uint32_item*)item, type);
break;
case VERSE_FACE_QUAT_REAL32: /* parent item has to exist */
vnode = (((quat_real32_item*)item)->vlayer)->vnode;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_real32_item*)item)->id );
if(vface != NULL)
send_verse_face_corner_quat_real32((quat_real32_item*)item, type);
break;
}
}
/*
* return VerseLayer with certain content (vertexes, polygons, in the
* future: weight, red color, etc.)
*/
VLayer* find_verse_layer_type(VGeomData *geom, short content)
{
struct VLayer *vlayer = NULL;
switch(content) {
case VERTEX_LAYER:
/* VERTEX_LAYER equals 0 and vertex layer is
* always in 1st layer */
vlayer = geom->layers.da.items[VERTEX_LAYER];
break;
case POLYGON_LAYER:
/* POLYGON_LAYER equals 1 and vertex layer is
* always in 2nd layer */
vlayer = geom->layers.da.items[POLYGON_LAYER];
break;
}
return vlayer;
}
/*
* increase references of VerseVerts of new VerseFace
*/
static void increase_verse_verts_references(VerseFace *vface)
{
if(vface->vvert0) vface->vvert0->counter++;
if(vface->vvert1) vface->vvert1->counter++;
if(vface->vvert2) vface->vvert2->counter++;
if(vface->vvert3) vface->vvert3->counter++;
}
/*
* move VerseFace from list of orphans to dlist of VerseFaces (if VerseFace was only changed
* then this VerseFace is only removed from list of orphans)
*/
static void move_face_orphan_to_dlist(VNode *vnode, VLayer *vlayer, VerseFace *vface)
{
/* remove vface from list of orphans */
BLI_remlink(&(vlayer->orphans), vface);
/* increase references of all vertexes beying part of this face*/
increase_verse_verts_references(vface);
if(vface->flag & FACE_RECEIVED) {
/* set up vface flag */
vface->flag &= ~FACE_RECEIVED;
/* move vface to dynamic list of faces */
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
/* recalculate all vertex and faces normals */
recalculate_verseface_normals(vnode);
/* post create action (change local data) */
((VGeomData*)vnode->data)->post_polygon_create(vface);
}
else if(vface->flag & FACE_CHANGED) {
/* set up vface flag */
vface->flag &= ~FACE_CHANGED;
/* move vface to dynamic list of faces */
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
/* recalculate all vertex and faces normals */
recalculate_verseface_normals(vnode);
/* post create action (change local data) */
((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
}
}
/*
* find all VerseFaces waiting in queue, which needs id of new VerseVert
*/
static void find_unsent_faces(VNode *vnode, VerseVert *vvert)
{
VLayer *vlayer;
VerseFace *vface, *next_vface;
vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
if(vlayer) {
vface = vlayer->queue.first;
while(vface) {
next_vface = vface->next;
if(vface->vvert0==vvert) {
vface->v0 = vvert->id;
vface->counter--;
}
else if(vface->vvert1==vvert) {
vface->v1 = vvert->id;
vface->counter--;
}
else if(vface->vvert2==vvert) {
vface->v2 = vvert->id;
vface->counter--;
}
else if(vface->vvert3==vvert){
vface->v3 = vvert->id;
vface->counter--;
}
if(vface->counter<1 && !(vface->flag & FACE_SENT))
send_verse_face(vface);
vface = next_vface;
}
}
}
/*
* find all VerseFace orphans, which needs incoming VerseVert
*/
static void find_vlayer_orphans(VNode *vnode, VerseVert *vvert)
{
VLayer *vlayer;
VerseFace *vface, *next_vface;
unsigned int vertex_id = vvert->id;
vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
if(vlayer) {
vface = vlayer->orphans.first;
while(vface){
next_vface = vface->next;
if(vface->v0 == vertex_id) {
vface->vvert0 = vvert;
vface->counter--;
}
else if(vface->v1 == vertex_id) {
vface->vvert1 = vvert;
vface->counter--;
}
else if(vface->v2 == vertex_id) {
vface->vvert2 = vvert;
vface->counter--;
}
else if(vface->v3 == vertex_id) {
vface->vvert3 = vvert;
vface->counter--;
}
if(vface->counter<1) {
/* moving VerseFace orphan to dlist */
move_face_orphan_to_dlist(vnode, vlayer, vface);
}
vface = next_vface;
}
}
}
/*
* return number of VerseVerts missing to incoming VerseFace, set up pointers
* at VerseVerts
*/
static unsigned short test_incoming_verseface(VGeomData *geom, VerseFace *vface)
{
struct VLayer *vert_layer;
struct VerseVert *vvert;
int counter=0;
vert_layer = find_verse_layer_type(geom, VERTEX_LAYER);
if(vface->v0 != -1){
vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v0);
if(vvert==NULL) counter++;
else vface->vvert0 = vvert;
}
if(vface->v1 != -1){
vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v1);
if(vvert==NULL) counter++;
else vface->vvert1 = vvert;
}
if(vface->v2 != -1){
vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v2);
if(vvert==NULL) counter++;
else vface->vvert2 = vvert;
}
if(vface->v3 != -1){
vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v3);
if(vvert==NULL) counter++;
else vface->vvert3 = vvert;
}
return counter;
}
/*
* try to find changed VerseFace in sending queue
*/
static VerseFace* find_changed_verse_face_in_queue(VLayer *vlayer, uint32 polygon_id)
{
struct VerseFace *vface = vlayer->queue.first;
while(vface){
if(vface->id == polygon_id && vface->flag & FACE_CHANGED) {
return vface;
}
vface = vface->next;
}
return NULL;
}
/*
* try to find VerseFace in queue
*/
static VerseFace* find_verse_face_in_queue(
VLayer *vlayer,
VNodeID node_id,
uint32 polygon_id,
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
struct VerseFace *vface = vlayer->queue.first;
while(vface){
if((vface->v0==v0) && (vface->v1==v1) && (vface->v2==v2) && (vface->v3==v3)){
vface->id = polygon_id;
vface->vlayer = vlayer;
return vface;
}
vface = vface->next;
}
return NULL;
}
/*
* try to find VerseVert in queue
*/
static VerseVert* find_verse_vert_in_queue(
VLayer *vlayer,
VNodeID node_id,
uint32 vertex_id,
real32 x,
real32 y,
real32 z)
{
struct VerseVert *vvert = vlayer->queue.first;
while(vvert){
if((vvert->vlayer->vnode->id == node_id) && (vvert->co[0] == x) && (vvert->co[1] == y) && (vvert->co[2] == z))
{
vvert->id = vertex_id;
vvert->vlayer = vlayer;
return vvert;
}
vvert = vvert->next;
}
return NULL;
}
/*
* send quat of float values to verse server (4x32 bits)
*/
void send_verse_face_corner_quat_real32(quat_real32_item *item, short type)
{
verse_send_g_polygon_set_corner_real32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value[0],
item->value[1],
item->value[2],
item->value[3]);
}
/*
* send quat of unsigned int values to verse server (4x32 bits)
*/
void send_verse_face_corner_quat_uint32(quat_uint32_item *item, short type)
{
verse_send_g_polygon_set_corner_uint32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value[0],
item->value[1],
item->value[2],
item->value[3]);
}
/*
* send float value (32 bits) to verse server
*/
void send_verse_face_real32(real32_item *item, short type)
{
verse_send_g_polygon_set_face_real32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value);
}
/*
* send unsigned integer (32 bits) to verse server
*/
void send_verse_face_uint32(uint32_item *item, short type)
{
verse_send_g_polygon_set_face_uint32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value);
}
/*
* send unsigned char (8 bits) to verse server
*/
void send_verse_face_uint8(uint8_item *item, short type)
{
verse_send_g_polygon_set_face_uint8(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value);
}
/*
* send vector of float values to verse server (3x32 bits)
*/
void send_verse_vert_vec_real32(vec_real32_item *item, short type)
{
verse_send_g_vertex_set_xyz_real32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value[0],
item->value[1],
item->value[2]);
}
/*
* send float value (32 bits) to verse server
*/
void send_verse_vert_real32(real32_item *item, short type)
{
verse_send_g_vertex_set_real32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value);
}
/*
* send unsigned integer (32 bits) to verse server
*/
void send_verse_vert_uint32(uint32_item *item, short type)
{
verse_send_g_vertex_set_uint32(
item->vlayer->vnode->id,
item->vlayer->id,
item->id,
item->value);
}
/*
* send delete command to verse server
*/
void send_verse_vertex_delete(VerseVert *vvert)
{
verse_session_set(vvert->vlayer->vnode->session->vsession);
vvert->flag |= VERT_OBSOLETE;
verse_send_g_vertex_delete_real32(vvert->vlayer->vnode->id, vvert->id);
}
/*
* send VerseLayer to verse server
*/
void send_verse_layer(VLayer *vlayer)
{
verse_session_set(vlayer->vnode->session->vsession);
verse_send_g_layer_create(
vlayer->vnode->id,
vlayer->id,
vlayer->name,
vlayer->type,
vlayer->def_int,
vlayer->def_real);
}
/*
* send VerseVert to verse server
*/
void send_verse_vertex(VerseVert *vvert)
{
/* new vertex position will not be sent, when vertex was deleted */
if(vvert->flag & VERT_OBSOLETE) return;
verse_session_set(vvert->vlayer->vnode->session->vsession);
verse_send_g_vertex_set_xyz_real32(
vvert->vlayer->vnode->id,
vvert->vlayer->id,
vvert->id,
vvert->co[0],
vvert->co[2],
-vvert->co[1]);
}
/*
* send delete command to verse server
*/
void send_verse_face_delete(VerseFace *vface)
{
verse_session_set(vface->vlayer->vnode->session->vsession);
vface->flag |= FACE_DELETED;
verse_send_g_polygon_delete(vface->vlayer->vnode->id, vface->id);
}
/*
* send VerseFace to verse server
*/
static void send_verse_face(VerseFace *vface)
{
verse_session_set(vface->vlayer->vnode->session->vsession);
vface->flag |= FACE_SENT;
if(vface->v3 != -1) {
verse_send_g_polygon_set_corner_uint32(
vface->vlayer->vnode->id,
vface->vlayer->id,
vface->id,
vface->v0,
vface->v3, /* verse use clock-wise winding */
vface->v2,
vface->v1); /* verse use clock-wise winding */
}
else {
verse_send_g_polygon_set_corner_uint32(
vface->vlayer->vnode->id,
vface->vlayer->id,
vface->id,
vface->v0,
vface->v2, /* verse use clock-wise winding */
vface->v1, /* verse use clock-wise winding */
vface->v3);
}
}
/*
* free VerseVert
*/
static void free_verse_vertex(VLayer *vlayer, VerseVert *vvert)
{
/* free VerseVert */
BLI_freelinkN(&(vlayer->orphans), vvert);
}
/*
* free VerseFace (and blender face)
*/
static void free_verse_face(VLayer *vlayer, VerseFace *vface)
{
/* free VerseFace */
BLI_dlist_free_item(&(vlayer->dl), (unsigned int)vface->id);
}
/*
* free VerseLayer data
*/
static void free_verse_layer_data(VNode *vnode, VLayer *vlayer)
{
struct VerseFace *vface;
struct VerseVert *vvert;
/* set up EditVert->vvert and EditFace->vface pointers to NULL */
switch(vlayer->content) {
case VERTEX_LAYER:
vvert = (VerseVert*)vlayer->dl.lb.first;
while(vvert) {
((VGeomData*)vnode->data)->post_vertex_free_constraint(vvert);
vvert = vvert->next;
}
break;
case POLYGON_LAYER:
vface = (VerseFace*)vlayer->dl.lb.first;
while(vface) {
((VGeomData*)vnode->data)->post_polygon_free_constraint(vface);
vface = vface->next;
}
break;
default:
break;
}
/* free Verse Layer name */
MEM_freeN(vlayer->name);
/* destroy VerseLayer data (vertexes, polygons, etc.) */
BLI_dlist_destroy(&(vlayer->dl));
/* free unsent data */
BLI_freelistN(&(vlayer->queue));
/* free orphans */
BLI_freelistN(&(vlayer->orphans));
}
/*
* free all unneeded VerseVerts waiting for deleting
*/
static void free_unneeded_verseverts_of_verseface(VNode *vnode, VerseFace *vface)
{
struct VLayer *vert_vlayer;
/* find layer containing vertexes */
vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
/* free all "deleted" VerseVert waiting for deleting this VerseFace */
if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
free_verse_vertex(vert_vlayer, vface->vvert0);
vface->vvert0 = NULL;
}
if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
free_verse_vertex(vert_vlayer, vface->vvert1);
vface->vvert1 = NULL;
}
if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
free_verse_vertex(vert_vlayer, vface->vvert2);
vface->vvert2 = NULL;
}
if((vface->vvert3) && (vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
free_verse_vertex(vert_vlayer, vface->vvert3);
vface->vvert3 = NULL;
}
}
/*
* This function create VerseVert and returns pointer on this vertex
*/
VerseVert* create_verse_vertex(
VLayer *vlayer,
uint32 vertex_id,
real32 x,
real32 y,
real32 z)
{
struct VerseVert *vvert;
vvert = (VerseVert*)MEM_mallocN(sizeof(VerseVert), "VerseVert");
/* set up pointer on parent node */
vvert->vlayer = vlayer;
vvert->id = vertex_id;
/* position */
vvert->co[0] = x;
vvert->co[1] = y;
vvert->co[2] = z;
/* normal */
vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
/* blender internals */
vvert->flag = 0;
vvert->counter = 0;
vvert->vertex = NULL;
/* increase layer counter of vertexes */
vlayer->counter++;
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
*/
VerseFace* create_verse_face(
VLayer *vlayer,
uint32 polygon_id,
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
struct VerseFace *vface;
vface = (VerseFace*)MEM_mallocN(sizeof(VerseFace), "VerseFace");
/* verse data */
vface->vlayer = vlayer;
vface->id = polygon_id;
vface->vvert0 = NULL;
vface->vvert1 = NULL;
vface->vvert2 = NULL;
vface->vvert3 = NULL;
vface->v0 = v0;
vface->v1 = v1;
vface->v2 = v2;
vface->v3 = v3;
/* blender data */
vface->face = NULL;
vface->flag = 0;
vface->counter = 4;
/* increase layer counter of faces */
vlayer->counter++;
return vface;
}
/*
* create and return VerseLayer
*/
VLayer *create_verse_layer(
VNode *vnode,
VLayerID layer_id,
const char *name,
VNGLayerType type,
uint32 def_integer,
real64 def_real)
{
struct VLayer *vlayer;
/* add layer to the DynamicList */
vlayer = (VLayer*)MEM_mallocN(sizeof(VLayer), "VerseLayer");
/* store all relevant info to the vlayer and set up vlayer */
vlayer->vnode = vnode;
vlayer->id = layer_id;
vlayer->name = (char*)MEM_mallocN(sizeof(char)*(sizeof(name)+1),"Verse Layer name");
strcpy(vlayer->name, name);
vlayer->type = type;
vlayer->def_int = def_integer;
vlayer->def_real = def_real;
if((type == VN_G_LAYER_VERTEX_XYZ) && (layer_id == 0))
vlayer->content = VERTEX_LAYER;
else if((type == VN_G_LAYER_POLYGON_CORNER_UINT32) && (layer_id == 1))
vlayer->content = POLYGON_LAYER;
else
vlayer->content = -1;
/* initialize DynamicList in the vlayer (vertexes, polygons, etc.)*/
BLI_dlist_init(&(vlayer->dl));
/* initialization of queue of layer */
vlayer->queue.first = vlayer->queue.last = NULL;
/* initialization of list of orphans */
vlayer->orphans.first = vlayer->orphans.last = NULL;
/* initialize number of sent items (vertexes, faces, etc) */
vlayer->counter = 0;
/* initialize flag */
vlayer->flag = 0;
/* set up methods */
vlayer->post_layer_create = post_layer_create;
vlayer->post_layer_destroy = post_layer_destroy;
return vlayer;
}
/*
* create geometry data
*/
VGeomData *create_geometry_data(void)
{
struct VGeomData *geom;
geom = (VGeomData*)MEM_mallocN(sizeof(VGeomData), "VerseGeometryData");
BLI_dlist_init(&(geom->layers));
geom->vlink = NULL;
geom->queue.first = geom->queue.last = NULL;
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;
geom->post_vertex_delete = post_vertex_delete;
geom->post_vertex_free_constraint = post_vertex_free_constraint;
geom->post_polygon_create = post_polygon_create;
geom->post_polygon_set_corner = post_polygon_set_corner;
geom->post_polygon_delete = post_polygon_delete;
geom->post_polygon_free_constraint = post_polygon_free_constraint;
geom->post_geometry_free_constraint = post_geometry_free_constraint;
geom->post_polygon_set_uint8 = post_polygon_set_uint8;
return geom;
}
/* Create item containing 4 floats */
static quat_real32_item *create_quat_real32_item(
VLayer *vlayer,
uint32 item_id,
real32 v0,
real32 v1,
real32 v2,
real32 v3)
{
struct quat_real32_item *item;
item = (quat_real32_item*)MEM_mallocN(sizeof(quat_real32_item), "quat_real32_item");
item->vlayer = vlayer;
item->id = item_id;
item->value[0] = v0;
item->value[1] = v1;
item->value[2] = v2;
item->value[3] = v3;
return item;
}
/* Create item containing 1 float */
static real32_item *create_real32_item(VLayer *vlayer, uint32 item_id, real32 value)
{
struct real32_item *item;
item = (real32_item*)MEM_mallocN(sizeof(real32_item), "real32_item");
item->vlayer = vlayer;
item->id = item_id;
item->value = value;
return item;
}
/* Create item containing 1 integer */
static uint32_item *create_uint32_item(VLayer *vlayer, uint32 item_id, uint32 value)
{
struct uint32_item *item;
item = (uint32_item*)MEM_mallocN(sizeof(uint32_item), "uint32_item");
item->vlayer = vlayer;
item->id = item_id;
item->value = value;
return item;
}
/* Create item containing 1 byte */
static uint8_item *create_uint8_item(VLayer *vlayer, uint32 item_id, uint8 value)
{
struct uint8_item *item;
item = (uint8_item*)MEM_mallocN(sizeof(uint8_item), "uint8_item");
item->vlayer = vlayer;
item->id = item_id;
item->value = value;
return item;
}
/*
* callback function: vertex crease was set
*/
static void cb_g_crease_set_vertex(
void *user_data,
VNodeID node_id,
const char *layer,
uint32 def_crease)
{
}
/*
* we have to test corretness of incoming data from verse server
* no two vertexes can have the same index
*/
static char test_polygon_set_corner_uint32(
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
if((v0==v1) || (v0==v2) || (v0==v3) || (v1==v2) || (v1==v3) || (v2==v3))
return 0;
else
return 1;
}
/*
* try to find verse layer in sending queue of verse geometry node
*/
static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id)
{
struct VLayer *vlayer;
/* try to find verse layyer in sending queue */
vlayer = ((VGeomData*)vnode->data)->queue.first;
while(vlayer) {
if(vlayer->id==layer_id) return vlayer;
vlayer = vlayer->next;
}
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: edge crease was set
*/
static void cb_g_crease_set_edge(
void *user_data,
VNodeID node_id,
const char *layer,
uint32 def_crease)
{
}
/*
* callback function: float value for polygon was set up
*/
static void cb_g_polygon_set_face_real32(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 polygon_id,
real32 value)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct real32_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
if(item) {
item->value = value;
}
else {
item = create_real32_item(vlayer, polygon_id, value);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: int values for polygon was set up
*/
static void cb_g_polygon_set_face_uint32(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 polygon_id,
uint32 value)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct uint32_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
if(item) {
item->value = value;
}
else {
item = create_uint32_item(vlayer, polygon_id, value);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: uint8 value for polygon was set up
*/
static void cb_g_polygon_set_face_uint8(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 polygon_id,
uint8 value)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct uint8_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
if(item) {
item->value = value;
}
else {
item = create_uint8_item(vlayer, polygon_id, value);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: float value for polygon corner was set up
*/
static void cb_g_polygon_set_corner_real32(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 polygon_id,
real32 v0,
real32 v1,
real32 v2,
real32 v3)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct quat_real32_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
if(item) {
item->value[0] = v0;
item->value[1] = v1;
item->value[2] = v2;
item->value[3] = v3;
}
else {
item = create_quat_real32_item(vlayer, polygon_id, v0, v1, v2, v3);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: polygon is deleted
*/
static void cb_g_polygon_delete(
void *user_data,
VNodeID node_id,
uint32 polygon_id)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
VNode *vnode;
VLayer *vlayer;
VerseFace *vface;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = BLI_dlist_find_link(&(session->nodes), node_id);
/* find layer containing faces */
vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
/* find wanted VerseFace */
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);
/* decrease references at coresponding VerseVertexes */
vface->vvert0->counter--;
vface->vvert1->counter--;
vface->vvert2->counter--;
if(vface->vvert3) vface->vvert3->counter--;
/* delete unneeded VerseVertexes */
free_unneeded_verseverts_of_verseface(vnode, vface);
free_verse_face(vlayer, vface);
}
/*
* callback function: new polygon (face) created or existing polygon was changed
*/
static void cb_g_polygon_set_corner_uint32(
void *user_data,
VNodeID node_id,
VLayerID layer_id,
uint32 polygon_id,
uint32 v0,
uint32 v1,
uint32 v2,
uint32 v3)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct VerseFace *vface=NULL;
if(!session) return;
/* try to find VerseNode */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode) return;
/* try to find VerseLayer */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
if(!vlayer) return;
/* we have to test coretness of incoming data */
if(!test_polygon_set_corner_uint32(v0, v1, v2, v3)) return;
/* Blender uses different order of vertexes */
if(v3!=-1) { /* quat swap */
unsigned int v; v = v1; v1 = v3; v3 = v;
}
else { /* triangle swap */
unsigned int v; v = v1; v1 = v2; v2 = v;
}
/* try to find VerseFace */
vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)polygon_id);
/* try to find modified VerseFace */
if(!vface) {
vface = find_changed_verse_face_in_queue(vlayer, polygon_id);
if(vface) {
BLI_remlink(&(vlayer->queue), (void*)vface);
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
}
}
if(!vface) {
/* try to find VerseFace in list of VerseVaces created by me and set up polygon and
* 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){
/* I creeated this face ... remove VerseFace from queue */
BLI_remlink(&(vlayer->queue), (void*)vface);
}
else {
/* some other client created this face*/
vface = create_verse_face(vlayer, polygon_id, v0, v1, v2, v3);
}
vface->flag &= ~FACE_SENT;
/* return number of missing verse vertexes */
vface->counter = test_incoming_verseface((VGeomData*)vnode->data, vface);
if(vface->counter < 1) {
/* when VerseFace received all needed VerseFaces, then it is moved
* to list of VerseFaces */
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
increase_verse_verts_references(vface);
recalculate_verseface_normals(vnode);
((VGeomData*)vnode->data)->post_polygon_create(vface);
}
else {
/* when all needed VerseVertexes weren't received, then VerseFace is moved to
* the list of orphans waiting on needed vertexes */
vface->flag |= FACE_RECEIVED;
BLI_addtail(&(vlayer->orphans), (void*)vface);
}
}
else {
VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
/* 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;
/* 1st corner */
if(vface->vvert0->id != v0) {
/* decrease references of obsolete vertexes*/
vface->vvert0->counter--;
/* delete this vertex, when it isn't used by any face and it was marked as deleted */
if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
free_verse_vertex(vert_vlayer, vface->vvert0);
}
/* try to set up new pointer at verse vertex */
vface->v0 = v0;
vface->vvert0 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v0);
if(vface->vvert0) {
/* increase references at new vertex */
vface->vvert0->counter++;
/* decrease count of needed vertex to receive */
vface->counter--;
}
}
else
/* this corner wasn't changed */
vface->counter--;
/* 2nd corner */
if(vface->vvert1->id != v1) {
vface->vvert1->counter--;
if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
free_verse_vertex(vert_vlayer, vface->vvert1);
}
vface->v1 = v1;
vface->vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v1);
if(vface->vvert1) {
vface->vvert1->counter++;
vface->counter--;
}
}
else
vface->counter--;
/* 3rd corner */
if(vface->vvert2->id != v2) {
vface->vvert2->counter--;
if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
free_verse_vertex(vert_vlayer, vface->vvert2);
}
vface->v2 = v2;
vface->vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v2);
if(vface->vvert2) {
vface->vvert2->counter++;
vface->counter--;
}
}
else
vface->counter--;
/* 4th corner */
if(vface->vvert3) {
if(vface->vvert3->id != v3) {
vface->vvert3->counter--;
if((vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
free_verse_vertex(vert_vlayer, vface->vvert3);
}
vface->v3 = v3;
if(v3 != -1) {
vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
if(vface->vvert3) {
vface->vvert3->counter++;
vface->counter--;
}
}
else {
/* this is some special case, this face hase now only 3 corners
* quat -> triangle */
vface->vvert3 = NULL;
vface->counter--;
}
}
}
else if(v3 != -1)
/* this is some special case, 4th corner of this polygon was created
* triangle -> quat */
vface->v3 = v3;
vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
if(vface->vvert3) {
vface->vvert3->counter++;
vface->counter--;
}
else {
vface->v3 = -1;
vface->counter--;
}
vface->flag &= ~FACE_SENT;
vface->flag |= FACE_CHANGED;
if(vface->counter<1) {
vface->flag &= ~FACE_CHANGED;
recalculate_verseface_normals(vnode);
((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
}
else {
/* when all needed VerseVertexes weren't received, then VerseFace is added to
* the list of orphans waiting on needed vertexes */
BLI_dlist_rem_item(&(vlayer->dl), vface->id);
BLI_addtail(&(vlayer->orphans), (void*)vface);
}
}
}
/*
* callback function: float value was set up for VerseVert with vertex_id
*/
static void cb_g_vertex_set_real32(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 vertex_id,
real32 value)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct real32_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), vertex_id);
if(item) {
item->value = value;
}
else {
item = create_real32_item(vlayer, vertex_id, value);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: int value was set up for VerseVert with vertex_id
*/
static void cb_g_vertex_set_uint32(
void *user_def,
VNodeID node_id,
VLayerID layer_id,
uint32 vertex_id,
uint32 value)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
struct uint32_item *item;
if(!session) return;
/* find needed node (we can be sure, that it is geometry node) */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
/* find layer containing uint_8 data */
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
/* try to find item*/
item = BLI_dlist_find_link(&(vlayer->dl), vertex_id);
if(item) {
item->value = value;
}
else {
item = create_uint32_item(vlayer, vertex_id, value);
BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
}
}
/*
* callback function: polygon was deleted
*/
static void cb_g_vertex_delete_real32(
void *user_data,
VNodeID node_id,
uint32 vertex_id)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
VNode *vnode=NULL;
VLayer *vert_vlayer=NULL;
VerseVert *vvert=NULL;
if(!session) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
vvert = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vertex_id);
if(!vvert) return;
if(vvert->counter < 1) {
((VGeomData*)vnode->data)->post_vertex_delete(vvert);
BLI_dlist_free_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
}
else {
/* some VerseFace(s) still need VerseVert, remove verse vert from
* list verse vertexes and put it to list of orphans */
vvert->flag |= VERT_DELETED;
BLI_dlist_rem_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
BLI_addtail(&(vert_vlayer->orphans), vvert);
}
}
/*
* callback function: position of one vertex was changed or new vertex was created
*/
static void cb_g_vertex_set_xyz_real32(
void *user_data,
VNodeID node_id,
VLayerID layer_id,
uint32 vertex_id,
real32 x,
real32 y,
real32 z)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode = NULL;
struct VLayer *vlayer = NULL;
struct VerseVert *vvert = NULL;
real32 tmp;
if(!session) return;
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode)return;
vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
if(!vlayer) return;
/* switch axis orientation */
tmp = y;
y = -z;
z = tmp;
if(vlayer->id == 0) {
/* try to pick up verse vert from DynamicList */
vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)vertex_id);
if(vvert) {
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)) {
/* 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);
}
}
}
else {
/* create new verse vert */
/* test if we are authors of this vertex :-) */
vvert = find_verse_vert_in_queue(vlayer, node_id, vertex_id, x, y, z);
if(vvert) {
/* remove vert from queue */
BLI_remlink(&(vlayer->queue), (void*)vvert);
/* add vvert to the dynamic list */
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
/* set VerseVert flags */
vvert->flag |= VERT_RECEIVED;
if(!(vvert->flag & VERT_POS_OBSOLETE))
vvert->flag &= ~VERT_LOCKED;
/* find VerseFaces orphans */
find_vlayer_orphans(vnode, vvert);
/* find unsent VerseFaces */
find_unsent_faces(vnode, vvert);
}
else {
/* create new VerseVert */
vvert = create_verse_vertex(vlayer, vertex_id, x, y, z);
/* add VerseVert to list of VerseVerts */
BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
/* set VerseVert flags */
vvert->flag |= VERT_RECEIVED;
/* find VerseFaces orphans */
find_vlayer_orphans(vnode, vvert);
}
((VGeomData*)vnode->data)->post_vertex_create(vvert);
}
}
}
/*
* callback function for destroyng of verse layer
*/
static void cb_g_layer_destroy(
void *user_data,
VNodeID node_id,
VLayerID layer_id)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VLayer *vlayer;
if(!session) return;
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), node_id);
if(!vnode) return;
vlayer = (VLayer*) BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), layer_id);
if(vlayer){
/* free VerseLayer data */
free_verse_layer_data(vnode, vlayer);
/* remove VerseLayer from list of verse layers */
BLI_dlist_rem_item(&(((VGeomData*)vnode->data)->layers), layer_id);
/* do client dependent actions */
vlayer->post_layer_destroy(vlayer);
/* free vlayer itself */
MEM_freeN(vlayer);
}
}
/*
* callback function: new layer was created
*/
static void cb_g_layer_create(
void *user_data,
VNodeID node_id,
VLayerID layer_id,
const char *name,
VNGLayerType type,
uint32 def_integer,
real64 def_real)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode=NULL;
struct VLayer *vlayer=NULL;
if(!session) return;
/* find node of this layer*/
vnode = BLI_dlist_find_link(&(session->nodes), node_id);
if(!vnode) return;
/* when we created this layer, then subscribe to this layer */
if(vnode->owner_id == VN_OWNER_MINE || session->flag & VERSE_AUTOSUBSCRIBE)
verse_send_g_layer_subscribe(node_id, layer_id, 0);
/* try to find */
if(vnode->owner_id == VN_OWNER_MINE)
vlayer = find_vlayer_in_sending_queue(vnode, layer_id);
if(vlayer) {
/* remove vlayer form sending queue add verse layer to list of verse layers */
BLI_remlink(&((VGeomData*)vnode->data)->queue, vlayer);
BLI_dlist_add_item_index(&((VGeomData*)vnode->data)->layers, (void*)vlayer, (unsigned int)vlayer->id);
/* send all not sent vertexes to verse server
* other items waiting in sending queue will be automaticaly sent to verse server,
* when verse vertexes will be received from verse server */
if((vlayer->type == VN_G_LAYER_VERTEX_XYZ) && (layer_id==0)) {
struct VerseVert *vvert = (VerseVert*)vlayer->queue.first;
while(vvert) {
send_verse_vertex(vvert);
vvert = vvert->next;
}
}
}
else {
/* create new VerseLayer */
vlayer = create_verse_layer(vnode, layer_id, name, type, def_integer, def_real);
/* add layer to the list of VerseLayers */
BLI_dlist_add_item_index(&(((VGeomData*)vnode->data)->layers), (void*)vlayer, (unsigned int)layer_id);
}
vlayer->flag |= LAYER_RECEIVED;
/* post callback function */
vlayer->post_layer_create(vlayer);
}
/*
* this function will send destroy commands for all VerseVertexes and
* VerseFaces to verse server, but it will not send destroy commands
* for VerseLayers or geometry node, it can be used in other functions
* (undo, destroy geom node, some edit mesh commands, ... ), parameter of
* this function has to be geometry verse node
*/
void destroy_geometry(VNode *vnode)
{
struct VLayer *vert_vlayer, *face_vlayer;
struct VerseFace *vface;
struct VerseVert *vvert;
if(vnode->type != V_NT_GEOMETRY) return;
face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
vface = face_vlayer->dl.lb.first;
while(vface) {
send_verse_face_delete(vface);
vface = vface->next;
}
vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
vvert = vert_vlayer->dl.lb.first;
while(vvert) {
send_verse_vertex_delete(vvert);
vvert = vvert->next;
}
/* own destruction of local verse date will be executed, when client will
* receive apropriate callback commands from verse server */
}
/*
* free VGeomData
*/
void free_geom_data(VNode *vnode)
{
struct VerseSession *session = vnode->session;
struct VLayer *vlayer;
if(vnode->data){
vlayer = (VLayer*)((VGeomData*)vnode->data)->layers.lb.first;
while(vlayer){
/* unsubscribe from layer */
if(session->flag & VERSE_CONNECTED)
verse_send_g_layer_unsubscribe(vnode->id, vlayer->id);
/* free VerseLayer data */
free_verse_layer_data(vnode, vlayer);
/* next layer */
vlayer = vlayer->next;
}
/* free constraint between vnode and mesh */
((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);
}
}
void set_geometry_callbacks(void)
{
/* new layer created */
verse_callback_set(verse_send_g_layer_create, cb_g_layer_create, NULL);
/* layer was destroyed */
verse_callback_set(verse_send_g_layer_destroy, cb_g_layer_destroy, NULL);
/* position of vertex was changed */
verse_callback_set(verse_send_g_vertex_set_xyz_real32, cb_g_vertex_set_xyz_real32, NULL);
/* vertex was deleted */
verse_callback_set(verse_send_g_vertex_delete_real32, cb_g_vertex_delete_real32, NULL);
/* callback functions for values being associated with vertexes */
verse_callback_set(verse_send_g_vertex_set_uint32, cb_g_vertex_set_uint32, NULL);
verse_callback_set(verse_send_g_vertex_set_real32, cb_g_vertex_set_real32, NULL);
/* new polygon was created / vertex(es) of polygon was set */
verse_callback_set(verse_send_g_polygon_set_corner_uint32, cb_g_polygon_set_corner_uint32, NULL);
/* polygon was deleted */
verse_callback_set(verse_send_g_polygon_delete, cb_g_polygon_delete, NULL);
/* callback functions for values being associated with polygon corners */
verse_callback_set(verse_send_g_polygon_set_corner_real32, cb_g_polygon_set_corner_real32, NULL);
/* callback functions for values being associated with faces */
verse_callback_set(verse_send_g_polygon_set_face_uint8, cb_g_polygon_set_face_uint8, NULL);
verse_callback_set(verse_send_g_polygon_set_face_uint32, cb_g_polygon_set_face_uint32, NULL);
verse_callback_set(verse_send_g_polygon_set_face_real32, cb_g_polygon_set_face_real32, NULL);
/* crease of vertex was set */
verse_callback_set(verse_send_g_crease_set_vertex, cb_g_crease_set_vertex, NULL);
/* crease of edge was set */
verse_callback_set(verse_send_g_crease_set_edge, cb_g_crease_set_edge, NULL);
}
#endif