344 lines
9.5 KiB
C
344 lines
9.5 KiB
C
/**
|
|
* $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 "mydevice.h"
|
|
|
|
#include "BKE_verse.h"
|
|
#include "BKE_image.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "BDR_drawmesh.h"
|
|
|
|
#include "BIF_verse.h"
|
|
#include "BIF_space.h"
|
|
|
|
/*
|
|
* unsubscribe from verse bitmap
|
|
*/
|
|
void unsubscribe_from_bitmap_node(VNode *vnode)
|
|
{
|
|
if(vnode->type != V_NT_BITMAP) return;
|
|
|
|
/* TODO */
|
|
}
|
|
|
|
/*
|
|
* upload image to verse server
|
|
*/
|
|
void push_image_to_verse_server(VerseSession *session, Image *image)
|
|
{
|
|
ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
|
|
struct VNode *vnode;
|
|
|
|
if(!session) return;
|
|
|
|
if(!(session->flag & VERSE_CONNECTED)) return;
|
|
|
|
/* create "my" new object VerseNode */
|
|
vnode= create_verse_node(session, -1 , V_NT_BITMAP, VN_OWNER_MINE);
|
|
/* create object data */
|
|
vnode->data = create_bitmap_data();
|
|
|
|
/* set up name of VerseNode */
|
|
vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(image->id.name)-1), "object node name");
|
|
vnode->name[0] = '\0';
|
|
strcat(vnode->name, image->id.name+2);
|
|
|
|
/* set up dimension of image */
|
|
if(ibuf) {
|
|
((VBitmapData*)vnode->data)->width = ibuf->x;
|
|
((VBitmapData*)vnode->data)->height = ibuf->y;
|
|
}
|
|
else {
|
|
((VBitmapData*)vnode->data)->width = 0;
|
|
((VBitmapData*)vnode->data)->height = 0;
|
|
}
|
|
((VBitmapData*)(vnode->data))->height = 1;
|
|
|
|
/* set up pointers between Object and VerseNode */
|
|
((VBitmapData*)vnode->data)->image = (void*)image;
|
|
image->vnode = (void*)vnode;
|
|
|
|
/* add node to sending queue */
|
|
add_item_to_send_queue(&(session->queue), vnode, VERSE_NODE);
|
|
}
|
|
|
|
/*
|
|
* synchronize blender image channel (R,G,B,A) with verse bitmap layer
|
|
*/
|
|
void sync_blender_image_channel_with_verse_layer(VNode *vnode, VBitmapLayer *vblayer)
|
|
{
|
|
struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
|
|
struct ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
|
|
unsigned char *rect;
|
|
int x, y, height, t_width, i, channel=0;
|
|
|
|
if(!image) return;
|
|
|
|
if(!ibuf) return;
|
|
|
|
rect = (unsigned char*)ibuf->rect;
|
|
|
|
/* select channel due to verse layer name */
|
|
if(strcmp(vblayer->name,"col_r")==0)
|
|
channel = 0;
|
|
else if(strcmp(vblayer->name,"col_g")==0)
|
|
channel = 1;
|
|
else if(strcmp(vblayer->name, "col_b")==0)
|
|
channel = 2;
|
|
else if(strcmp(vblayer->name,"alpha")==0)
|
|
channel = 3;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf(" %s:%d\n", vblayer->name, channel);
|
|
#endif
|
|
|
|
height = ((VBitmapData*)(vnode->data))->height;
|
|
t_width = ((VBitmapData*)(vnode->data))->t_width;
|
|
|
|
i = (height-1)*t_width;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\ti:%d\n", i);
|
|
#endif
|
|
|
|
if(vblayer->type==VN_B_LAYER_UINT8) {
|
|
unsigned char *vuint8 = (unsigned char*)vblayer->data;
|
|
for(y=height-1; y>=0; y--, i=y*t_width)
|
|
for(x=0; x<ibuf->x; x++, rect+=4, i++)
|
|
rect[channel] = (char)vuint8[i];
|
|
}
|
|
|
|
allqueue(REDRAWIMAGE, 0);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
/*
|
|
* synchronize blender image with verse image
|
|
*/
|
|
void sync_blender_image_with_verse_bitmap_node(VNode *vnode)
|
|
{
|
|
struct VBitmapLayer *vblayer;
|
|
|
|
vblayer = ((VBitmapData*)(vnode->data))->layers.lb.first;
|
|
|
|
while(vblayer) {
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\tsyncing layer:");
|
|
#endif
|
|
sync_blender_image_channel_with_verse_layer(vnode, vblayer);
|
|
vblayer = vblayer->next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This function is called, when some other verse client change dimension of image.
|
|
* It is neccesary to reallocate blender image too, when dimension of verse image
|
|
* is different from blender image.
|
|
*/
|
|
void post_bitmap_dimension_set(VNode *vnode)
|
|
{
|
|
struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
|
|
struct ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
|
|
|
|
if(!image) return;
|
|
|
|
if(!ibuf) return;
|
|
|
|
if(vnode->owner_id == VN_OWNER_MINE) {
|
|
if( ((VBitmapData*)vnode->data)->layers.lb.first == NULL ) {
|
|
/* send all verse bitmap layers (RGBA) to verse server */
|
|
printf("\tsending all bitmap layers to verse server\n");
|
|
verse_send_b_layer_create(vnode->id, -1, "col_r", VN_B_LAYER_UINT8);
|
|
verse_send_b_layer_create(vnode->id, -1, "col_g", VN_B_LAYER_UINT8);
|
|
verse_send_b_layer_create(vnode->id, -1, "col_b", VN_B_LAYER_UINT8);
|
|
verse_send_b_layer_create(vnode->id, -1, "alpha", VN_B_LAYER_UINT8);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if((ibuf->x!=((VBitmapData*)vnode->data)->width) || (ibuf->y!=((VBitmapData*)vnode->data)->height)) {
|
|
struct VBitmapLayer *vblayer;
|
|
struct ImBuf *new_ibuf;
|
|
|
|
/* allocate new ibuf */
|
|
new_ibuf= IMB_allocImBuf(((VBitmapData*)vnode->data)->width,
|
|
((VBitmapData*)vnode->data)->height, 24, IB_rect, 0);
|
|
/* free old ibuf */
|
|
BKE_image_signal(image, NULL, IMA_SIGNAL_FREE);
|
|
/* set up pointer at new ibuf */
|
|
BKE_image_assign_ibuf(image, ibuf);
|
|
|
|
/* sync blender image with all verse layers */
|
|
vblayer = ((VBitmapData*)(vnode->data))->layers.lb.first;
|
|
while(vblayer) {
|
|
sync_blender_image_channel_with_verse_layer(vnode, vblayer);
|
|
vblayer = vblayer->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* when blender tries to upload image to verse server, then it is neccessary
|
|
* to push coresponding channel data to verse server, when verse bitmap layer
|
|
* was created
|
|
*/
|
|
void post_bitmap_layer_create(VBitmapLayer *vblayer)
|
|
{
|
|
struct VNode *vnode = vblayer->vnode;
|
|
struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
|
|
struct ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
|
|
unsigned char *rect;
|
|
short channel;
|
|
/* VNBTile tile[VN_B_TILE_SIZE*VN_B_TILE_SIZE];
|
|
unsigned int width, t_width, height, t_height, x, y, i, j; */
|
|
|
|
/* if this application doesn't try to upload this image to verse
|
|
* server then do nothing */
|
|
if(vnode->owner_id != VN_OWNER_MINE) return;
|
|
|
|
if(!image) return;
|
|
|
|
if(!ibuf) return;
|
|
|
|
rect = (unsigned char*)ibuf->rect;
|
|
|
|
if(strncmp(vblayer->name, "col_r", 5))
|
|
channel = 0;
|
|
else if(strncmp(vblayer->name, "col_g", 5))
|
|
channel = 1;
|
|
else if(strncmp(vblayer->name, "col_b", 5))
|
|
channel = 2;
|
|
else if(strncmp(vblayer->name, "alpha", 5))
|
|
channel = 3;
|
|
|
|
/* TODO: send all data of channel to verse server */
|
|
}
|
|
|
|
/*
|
|
* dummy function now
|
|
*/
|
|
void post_bitmap_layer_destroy(VBitmapLayer *vblayer)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* this function is executed, when some image changed tile comes from verse server,
|
|
* it is neccessary to do some crazy transformation here, because blender uses
|
|
* different (very unstandard) image coordinate system (begining of coordinate
|
|
* system is in bottom left corner) ... all other programs (including verse) has
|
|
* begining of image coordinate system in left top corner
|
|
*/
|
|
void post_bitmap_tile_set(VBitmapLayer *vblayer, unsigned int xs, unsigned int ys)
|
|
{
|
|
struct VNode *vnode = vblayer->vnode;
|
|
struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
|
|
struct ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
|
|
unsigned char *rect, *i_rect;
|
|
unsigned int x, y, t_width, t_height, height, m_ys, m_y, d, i, j, channel=0;
|
|
|
|
if(!image) return;
|
|
|
|
if(!ibuf) return;
|
|
|
|
/* select channel due to verse layer name */
|
|
if(strcmp(vblayer->name,"color_r")==0)
|
|
channel = 0;
|
|
else if(strcmp(vblayer->name,"color_g")==0)
|
|
channel = 1;
|
|
else if(strcmp(vblayer->name, "color_b")==0)
|
|
channel = 2;
|
|
else if(strcmp(vblayer->name,"transparency")==0)
|
|
channel = 3;
|
|
|
|
i_rect = rect = (unsigned char*)ibuf->rect;
|
|
|
|
/* width of verse image including all tiles */
|
|
t_width =((VBitmapData*)vnode->data)->t_width;
|
|
/* height of verse image including all tiles */
|
|
t_height =((VBitmapData*)vnode->data)->t_height;
|
|
/* height of blender image */
|
|
height = ((VBitmapData*)vnode->data)->height;
|
|
|
|
/* if the bitmap's dimensions are not integer multiples of the tile
|
|
* side length, eight, then d will not be zero (height of "uncomplete
|
|
* tile") */
|
|
d = VN_B_TILE_SIZE - (t_height - height);
|
|
/* mirrored coordination of received tile */
|
|
m_ys = t_height - ys - VN_B_TILE_SIZE;
|
|
|
|
/* ys and m_ys are y axis, where we will do some changes */
|
|
if(ys + VN_B_TILE_SIZE > height) {
|
|
m_ys = 0;
|
|
ys = ys + d - 1;
|
|
}
|
|
else {
|
|
m_ys = m_ys - VN_B_TILE_SIZE + d;
|
|
ys = ys + VN_B_TILE_SIZE - 1;
|
|
}
|
|
|
|
/* "index" of blender image */
|
|
j = m_ys*ibuf->x + xs;
|
|
/* index of verse image */
|
|
i = ys*t_width + xs;
|
|
|
|
/* pointer at image data, that will be changed in following loop */
|
|
rect = i_rect + 4*j;
|
|
|
|
/* it seems hackish, but I didn't find better solution :-/ */
|
|
if(vblayer->type==VN_B_LAYER_UINT8) {
|
|
unsigned char *vuint8 = (unsigned char*)vblayer->data;
|
|
for(y=ys, m_y = m_ys;
|
|
(m_y<m_ys+VN_B_TILE_SIZE) && (m_y<ibuf->y);
|
|
y--, m_y++, i=y*t_width+xs, j=m_y*ibuf->x+xs, rect=i_rect+4*j)
|
|
for(x=xs; (x<xs+VN_B_TILE_SIZE) && (x<ibuf->x); x++, rect+=4, i++, j++)
|
|
rect[channel] = (char)vuint8[i];
|
|
}
|
|
|
|
free_realtime_image(image);
|
|
|
|
/* redraw preview of image ... uncommented, because rendering
|
|
* was computed too often */
|
|
/* BIF_preview_changed(ID_TE); */
|
|
allqueue(REDRAWIMAGE, 0);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
|
|
#endif
|
|
|