2099 lines
57 KiB
C
2099 lines
57 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL 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.
|
|
*
|
|
* 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 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
|