diff options
author | Jiri Hnidek <jiri.hnidek@tul.cz> | 2006-08-20 19:22:56 +0400 |
---|---|---|
committer | Jiri Hnidek <jiri.hnidek@tul.cz> | 2006-08-20 19:22:56 +0400 |
commit | 2ee42ac01e6f4b154ac68976024af0615f7acb26 (patch) | |
tree | 9a2400a99bf7880a2f146c7a89bd2d8c0108374c /source/blender/blenkernel/intern/verse_object_node.c | |
parent | ffe630b452f4abb28c105fca2b8eb9fdb6e72370 (diff) |
Huge commit: VERSE
- All code is in #ifdef ... #endif
- Only make build system is supported and you have to add:
export WITH_VERSE=true
to user-def.mk file
- Blender can share only mesh objects and bitmaps now
- More informations can be found at wiki:
http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlender
http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlenderUserDoc
I hope, that I didn't forget at anything
Diffstat (limited to 'source/blender/blenkernel/intern/verse_object_node.c')
-rw-r--r-- | source/blender/blenkernel/intern/verse_object_node.c | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c new file mode 100644 index 00000000000..9e6de928ef0 --- /dev/null +++ b/source/blender/blenkernel/intern/verse_object_node.c @@ -0,0 +1,605 @@ +/** + * $Id$ + * + * ***** 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 "BIF_verse.h" + +#include "BKE_verse.h" + +#include "verse.h" + +/* function prototypes of static functions */ + +/* callback functions */ +static void cb_o_transform_pos_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const real32 *pos, const real32 *speed, const real32 *accelerate, const real32 *drag_normal, real32 drag); +static void cb_o_transform_rot_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const VNQuat32 *rot, const VNQuat32 *speed, const VNQuat32 *accelerate, const VNQuat32 *drag_normal, real32 drag); +static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z); +static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id); +static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id); + +/* other functions */ +static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink); +static void free_verse_link_data(struct VLink *vlink); + +/* + * find noy sent VerseLink in queue + */ +VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode) +{ + struct VLink *vlink; + + if(vnode->type!=V_NT_OBJECT) return NULL; + + vlink = ((VObjectData*)vnode->data)->queue.first; + while(vlink) { + if(vlink->target->id != -1) { + printf("\t vlink found, vnode target id %d\n", vlink->target->id); + return vlink; + } + vlink = vlink->next; + } + return NULL; +} + +/* + * find unsent VerseLink "pointing at this VerseNode" + */ +VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode) +{ + struct VNode *tmp; + struct VLink *vlink; + + tmp = session->nodes.lb.first; + + while(tmp) { + if(tmp->type==V_NT_OBJECT) { + vlink = ((VObjectData*)tmp->data)->queue.first; + while(vlink) { + if(vlink->target == vnode) + return vlink; + vlink = vlink->next; + } + } + tmp = tmp->next; + } + return NULL; +} + +/* + * send object position to verse server + */ +void send_verse_object_position(VNode *vnode) +{ + float tmp; + + ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY; + + tmp = -((VObjectData*)vnode->data)->pos[1]; + ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2]; + ((VObjectData*)vnode->data)->pos[2] = tmp; + + verse_send_o_transform_pos_real32( + vnode->id, /* node id */ + 0, /* time_s ... no interpolation */ + 0, /* time_f ... no interpolation */ + ((VObjectData*)vnode->data)->pos, + NULL, /* speed ... no interpolation */ + NULL, /* accelerate ... no interpolation */ + NULL, /* drag normal ... no interpolation */ + 0.0); /* drag ... no interpolation */ +} + +/* + * send object rotation to verse server + */ +void send_verse_object_rotation(VNode *vnode) +{ + float quat[4]; +/* float bvec[3], vvec[3];*/ + VNQuat32 rot; + + rot.x = ((VObjectData*)vnode->data)->rot[0]; + rot.y = ((VObjectData*)vnode->data)->rot[1]; + rot.z = ((VObjectData*)vnode->data)->rot[2]; + rot.w = ((VObjectData*)vnode->data)->rot[3]; + +/* + quat[0] = ((VObjectData*)vnode->data)->rot[0]; + quat[1] = ((VObjectData*)vnode->data)->rot[1]; + quat[2] = ((VObjectData*)vnode->data)->rot[2]; + quat[3] = ((VObjectData*)vnode->data)->rot[3]; + + QuatToEul(quat, bvec); + vvec[0] = bvec[0]; + vvec[1] = bvec[1]; + vvec[2] = bvec[2]; + EulToQuat(vvec, quat); + + rot.x = quat[0]; + rot.y = quat[1]; + rot.z = quat[2]; + rot.w = quat[3]; +*/ + + ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY; + + verse_send_o_transform_rot_real32( + vnode->id, /* node id */ + 0, /* time_s ... no interpolation */ + 0, /* time_f ... no interpolation */ + &rot, + NULL, /* speed ... no interpolation */ + NULL, /* accelerate ... no interpolation */ + NULL, /* drag normal ... no interpolation */ + 0.0); /* drag ... no interpolation */ +} + +/* + * send object rotation to verse server + */ +void send_verse_object_scale(VNode *vnode) +{ + ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY; + + verse_send_o_transform_scale_real32( + vnode->id, + ((VObjectData*)vnode->data)->scale[0], + ((VObjectData*)vnode->data)->scale[2], + ((VObjectData*)vnode->data)->scale[1]); +} + +/* + * send VerseLink to verse server + */ +void send_verse_link(VLink *vlink) +{ + verse_session_set(vlink->session->vsession); + + verse_send_o_link_set( + vlink->source->id, + vlink->id, + vlink->target->id, + vlink->label, + vlink->target_id); +} + +/* + * set up pointer at VerseLink of target node (geometry node, material node, etc.) + */ +static void set_target_node_link_pointer(VNode *vnode, VLink *vlink) +{ + switch (vnode->type) { + case V_NT_GEOMETRY: + ((VGeomData*)vnode->data)->vlink = vlink; + break; + default: + break; + } +} + +/* + * free VerseLink and it's label + */ +static void free_verse_link_data(VLink *vlink) +{ + MEM_freeN(vlink->label); +} + +/* + * create new VerseLink + */ +VLink *create_verse_link( + VerseSession *session, + VNode *source, + VNode *target, + uint16 link_id, + uint32 target_id, + const char *label) +{ + struct VLink *vlink; + + vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink"); + vlink->session = session; + vlink->source = source; + vlink->target = target; + vlink->id = link_id; + vlink->target_id = target_id; + + set_target_node_link_pointer(target, vlink); + + vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label"); + vlink->label[0] = '\0'; + strcat(vlink->label, label); + + vlink->flag = 0; + + vlink->post_link_set = post_link_set; + vlink->post_link_destroy = post_link_destroy; + + return vlink; +} + +/* + * free ObjectData (links, links in queue and lables of links) + */ +void free_object_data(VNode *vnode) +{ + struct VerseSession *session = vnode->session; + struct VObjectData *obj = (VObjectData*)vnode->data; + struct VLink *vlink; + + if(!obj) return; + + /* free all labels of links in dlist */ + vlink = obj->links.lb.first; + while(vlink){ + free_verse_link_data(vlink); + vlink = vlink->next; + } + + /* free all labels of links waiting in queue */ + vlink = obj->queue.first; + while(vlink){ + free_verse_link_data(vlink); + vlink = vlink->next; + } + /* free dynamic list and sendig queue of links */ + BLI_dlist_destroy(&(obj->links)); + BLI_freelistN(&(obj->queue)); + + /* free constraint between VerseNode and Object */ + obj->post_object_free_constraint(vnode); + + /* unsubscribe from receiving changes of transformation matrix */ + if(session->flag & VERSE_CONNECTED) + verse_send_o_transform_unsubscribe(vnode->id, 0); +} + +/* + * create new object data + */ +VObjectData *create_object_data(void) +{ + VObjectData *obj; + + obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData"); + obj->object = NULL; + BLI_dlist_init(&(obj->links)); + obj->queue.first = obj->queue.last = NULL; + obj->flag = 0; + + /* transformation matrix */ + obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0; + obj->rot[0] = obj->rot[1] = obj->rot[2] = 0.0; obj->rot[3] = 1; + obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0; + + /* transformation flags */ + obj->flag |= POS_SEND_READY; + obj->flag |= ROT_SEND_READY; + obj->flag |= SCALE_SEND_READY; + + /* set up pointers at post callback functions */ + obj->post_transform = post_transform; + obj->post_object_free_constraint = post_object_free_constraint; + + return obj; +} + +/* + * callback function: + */ +static void cb_o_transform_pos_real32( + void *user_data, + VNodeID node_id, + uint32 time_s, + uint32 time_f, + const real32 *pos, + const real32 *speed, + const real32 *accelerate, + const real32 *drag_normal, + real32 drag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + float vec[3], dt, tmp; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= POS_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY; + return; + } + + dt = time_s + time_f/(0xffff); + + /* we have to flip z and y coordinates, because verse and blender use different axis + * orientation */ + if(pos) { + vec[0] = pos[0]; + vec[1] = pos[1]; + vec[2] = pos[2]; + } + + if(speed) { + vec[0] += speed[0]*dt; + vec[1] += speed[1]*dt; + vec[2] += speed[2]*dt; + } + + if(accelerate) { + vec[0] += accelerate[0]*dt*dt/2; + vec[1] += accelerate[1]*dt*dt/2; + vec[2] += accelerate[2]*dt*dt/2; + } + + /* flip axis (due to verse spec) */ + tmp = vec[1]; + vec[1] = -vec[2]; + vec[2] = tmp; + + if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) || + (((VObjectData*)vnode->data)->pos[1] != vec[1]) || + (((VObjectData*)vnode->data)->pos[2] != vec[2])) + { + ((VObjectData*)vnode->data)->pos[0] = vec[0]; + ((VObjectData*)vnode->data)->pos[1] = vec[1]; + ((VObjectData*)vnode->data)->pos[2] = vec[2]; + + ((VObjectData*)vnode->data)->post_transform(vnode); + } +} + +/* + * callback function: + */ +static void cb_o_transform_rot_real32( + void *user_data, + VNodeID node_id, + uint32 time_s, + uint32 time_f, + const VNQuat32 *rot, + const VNQuat32 *speed, + const VNQuat32 *accelerate, + const VNQuat32 *drag_normal, + real32 drag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + float quat[4]={0, 0, 0, 0}, dt; +/* float vvec[3], bvec[3];*/ + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY; + return; + } + + dt = time_s + time_f/(0xffff); + + if(rot) { + quat[0] = rot->x; + quat[1] = rot->y; + quat[2] = rot->z; + quat[3] = rot->w; + } + + if(speed) { + quat[0] += speed->x*dt; + quat[1] += speed->y*dt; + quat[2] += speed->z*dt; + quat[3] += speed->w*dt; + } + + if(accelerate) { + quat[0] += accelerate->x*dt*dt/2; + quat[1] += accelerate->y*dt*dt/2; + quat[2] += accelerate->z*dt*dt/2; + quat[3] += accelerate->w*dt*dt/2; + } + +/* QuatToEul(quat, vvec); + bvec[0] = vvec[0]; + bvec[1] = vvec[1]; + bvec[2] = vvec[2]; + EulToQuat(bvec, quat);*/ + + if( (((VObjectData*)vnode->data)->rot[0] != quat[0]) || + (((VObjectData*)vnode->data)->rot[1] != quat[1]) || + (((VObjectData*)vnode->data)->rot[2] != quat[2]) || + (((VObjectData*)vnode->data)->rot[3] != quat[3])) + { + ((VObjectData*)vnode->data)->rot[0] = quat[0]; + ((VObjectData*)vnode->data)->rot[1] = quat[1]; + ((VObjectData*)vnode->data)->rot[2] = quat[2]; + ((VObjectData*)vnode->data)->rot[3] = quat[3]; + + ((VObjectData*)vnode->data)->post_transform(vnode); + } +} + +/* + * callback function: + */ +static void cb_o_transform_scale_real32( + void *user_data, + VNodeID node_id, + real32 scale_x, + real32 scale_y, + real32 scale_z) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + real32 tmp; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY; + + /* verse server sends automaticaly some stupid default values ... + * we have to ignore these values, when we created this object node */ + if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) { + ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY; + return; + } + + /* flip axis (verse spec) */ + tmp = scale_y; + scale_y = scale_z; + scale_z = tmp; + + /* z and y axis are flipped here too */ + if( (((VObjectData*)vnode->data)->scale[0] != scale_x) || + (((VObjectData*)vnode->data)->scale[1] != scale_y) || + (((VObjectData*)vnode->data)->scale[2] != scale_z)) + { + ((VObjectData*)vnode->data)->scale[0] = scale_x; + ((VObjectData*)vnode->data)->scale[1] = scale_y; + ((VObjectData*)vnode->data)->scale[2] = scale_z; + + ((VObjectData*)vnode->data)->post_transform(vnode); + } +} + +/* + * callback function: link between object node and some other node was created + */ +static void cb_o_link_set( + void *user_data, + VNodeID node_id, + uint16 link_id, + VNodeID link, + const char *label, + uint32 target_id) +{ + struct VLink *vlink; + struct VNode *source; + struct VNode *target; + + struct VerseSession *session = (VerseSession*)current_verse_session(); + + if(!session) return; + + source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link); + + if(!(source && target)) return; + + vlink = ((VObjectData*)source->data)->queue.first; + + if(vlink && (vlink->source==source) && (vlink->target==target)) { + /* remove VerseLink from sending queue */ + BLI_remlink(&(((VObjectData*)source->data)->queue), vlink); + /* add VerseLink to dynamic list of VerseLinks */ + BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); + /* send next link from sending queue */ + if(((VObjectData*)source->data)->queue.first) + send_verse_link(((VObjectData*)source->data)->queue.first); + /* set up VerseLink variables */ + vlink->flag = 0; + vlink->id = link_id; + vlink->target_id = target_id; + } + else { + /* create new VerseLink */ + vlink = create_verse_link(session, source, target, link_id, target_id, label); + /* add VerseLink to dynamic list of VerseLinks */ + BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); + } + + target->counter++; + + vlink->post_link_set(vlink); +} + +/* + * callback function: destroy link between two VerseNodes + */ +static void cb_o_link_destroy( + void *user_data, + VNodeID node_id, + uint16 link_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VLink *vlink; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id); + + if(vlink) { + vlink->target->counter--; + free_verse_link_data(vlink); + BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id); + } + + vlink->post_link_destroy(vlink); +} + +void set_object_callbacks(void) +{ + /* position of object was changed */ + verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL); + /* rotation of object was changed */ + verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL); + /* size of object was changed */ + verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL); + /* new link between nodes was created */ + verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL); + /* link between nodes was destroyed */ + verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL); +} + +#endif |