int igtl_export igtl_polydata_unpack(int type, void * byte_array, igtl_polydata_info * info, igtl_uint64 size) { /* size = number of ponits (not number of bytes). In case of vertices, this is specfied by size_vertices in igtl_polydata_header. */ igtl_polydata_header * header; char * ptr; igtl_uint32 * ptr32_src; igtl_uint32 * ptr32_src_end; igtl_uint32 * ptr32_dst; igtl_uint32 s; igtl_polydata_attribute_header * att_header; igtl_polydata_attribute * att; int total_name_length; int name_length; char name_buf[IGTL_POLY_MAX_ATTR_NAME_LEN+1]; unsigned int i; int n; if (byte_array == NULL || info == NULL || size == 0) { return 0; } /* POLYDATA header */ header = (igtl_polydata_header *) byte_array; if (igtl_is_little_endian()) { info->header.npoints = BYTE_SWAP_INT32(header->npoints); info->header.nvertices = BYTE_SWAP_INT32(header->nvertices); info->header.size_vertices = BYTE_SWAP_INT32(header->size_vertices); info->header.nlines = BYTE_SWAP_INT32(header->nlines); info->header.size_lines = BYTE_SWAP_INT32(header->size_lines); info->header.npolygons = BYTE_SWAP_INT32(header->npolygons); info->header.size_polygons = BYTE_SWAP_INT32(header->size_polygons); info->header.ntriangle_strips = BYTE_SWAP_INT32(header->ntriangle_strips); info->header.size_triangle_strips = BYTE_SWAP_INT32(header->size_triangle_strips); info->header.nattributes = BYTE_SWAP_INT32(header->nattributes); } else { memcpy(&(info->header), header, sizeof(igtl_polydata_header)); } /* Allocate memory to read data */ /* TODO: compare the size of info before copying the header. */ /* If the size doesn't change, avoid reallocation of memory. */ if (igtl_polydata_alloc_info(info) == 0) { return 0; } /* POINT section */ ptr = (char*) byte_array + sizeof(igtl_polydata_header); if (!igtl_is_little_endian()) { memcpy(info->points, ptr, sizeof(igtl_float32)*info->header.npoints*3); } else { ptr32_src = (igtl_uint32 *) ptr; ptr32_src_end = ptr32_src + info->header.npoints*3; ptr32_dst = (igtl_uint32 *) info->points; while (ptr32_src < ptr32_src_end) { *ptr32_dst = BYTE_SWAP_INT32(*ptr32_src); ptr32_dst ++; ptr32_src ++; } } ptr += sizeof(igtl_float32)*info->header.npoints*3; /* Check size parameters */ if (info->header.size_vertices%sizeof(igtl_uint32) != 0 || info->header.size_lines%sizeof(igtl_uint32) != 0 || info->header.size_polygons%sizeof(igtl_uint32) != 0 || info->header.size_triangle_strips%sizeof(igtl_uint32)) { /* More than one of size parameters is multiples of 4 (size of 32-bit value) */ return 0; } /* VERTICES section */ igtl_polydata_convert_byteorder_topology(info->vertices, (igtl_uint32*)ptr, info->header.size_vertices); ptr += info->header.size_vertices; /* LINES section */ igtl_polydata_convert_byteorder_topology(info->lines, (igtl_uint32*)ptr, info->header.size_lines); ptr += info->header.size_lines; /* POLYGONS section */ igtl_polydata_convert_byteorder_topology(info->polygons, (igtl_uint32*)ptr, info->header.size_polygons); ptr += info->header.size_polygons; /* TRIANGLE_STRIPS section */ igtl_polydata_convert_byteorder_topology(info->triangle_strips, (igtl_uint32*)ptr, info->header.size_triangle_strips); ptr += info->header.size_triangle_strips; /* Attribute header */ for (i = 0; i < info->header.nattributes; i ++) { att = &(info->attributes[i]); att_header = (igtl_polydata_attribute_header *) ptr; att->type = att_header->type; att->ncomponents = att_header->ncomponents; if (igtl_is_little_endian()) { att->n = BYTE_SWAP_INT32(att_header->n); } else { att->n = att_header->n; } ptr += sizeof(igtl_polydata_attribute_header); } /* Attribute names */ total_name_length = 0; name_buf[IGTL_POLY_MAX_ATTR_NAME_LEN] = '\0'; for (i = 0; i < info->header.nattributes; i ++) { name_length = strlen(ptr); if (name_length <= IGTL_POLY_MAX_ATTR_NAME_LEN) { info->attributes[i].name = malloc(name_length+1); strcpy(info->attributes[i].name, ptr); } else { /* invalid name length */ return 0; } total_name_length += (name_length+1); ptr += (name_length+1); } if (total_name_length % 2 > 0) { /* add padding */ ptr ++; } /* Attributes */ for (i = 0; i < info->header.nattributes; i ++) { if (info->attributes[i].type == IGTL_POLY_ATTR_TYPE_SCALAR) { n = info->attributes[i].ncomponents * info->attributes[i].n; s = n * sizeof(igtl_float32); } else if (info->attributes[i].type == IGTL_POLY_ATTR_TYPE_NORMAL) { n = 3 * info->attributes[i].n; s = n * sizeof(igtl_float32); } else if (info->attributes[i].type == IGTL_POLY_ATTR_TYPE_VECTOR) { n = 3 * info->attributes[i].n; s = n * sizeof(igtl_float32); } else /* TENSOR */ { n = 9 * info->attributes[i].n; s = n * sizeof(igtl_float32); } info->attributes[i].data = (igtl_float32*)malloc((size_t)s); ptr32_dst = (igtl_uint32*)info->attributes[i].data; ptr32_src = (igtl_uint32*)ptr; ptr32_src_end = ptr32_src + n; while (ptr32_src < ptr32_src_end) { *ptr32_dst = BYTE_SWAP_INT32(*ptr32_src); ptr32_dst ++; ptr32_src ++; } ptr += s; } return 1; }
int main( int argc, char * argv [] ) { /*** Message structures and byte array ***/ igtl_header header; void * body; igtl_polydata_info info; int rh; /* Comparison result for header */ int rb; /* Comparison result for body */ unsigned int i; int s; igtl_float32 * ptr_f; igtl_uint32 * ptr_i; igtl_uint64 body_size; static igtl_float32 points[8][3]={{0,0,0}, {1,0,0}, {1,1,0}, {0,1,0}, {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1}}; static igtl_uint32 poly[6][4]={{0,1,2,3}, {4,5,6,7}, {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7}}; static igtl_float32 attribute[8]={0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; /*** Generate test data ***/ /* Note that the size of polygon data (or other cell data) is calculated by * number of polygons * (number of points + 1) * '+ 1' is required because of the number of points in the polygon (uint32) * is stored at the begining of polygon data. */ igtl_polydata_init_info(&info); info.header.npoints = 8; info.header.nvertices = 0; info.header.size_vertices = 0; info.header.nlines = 0; info.header.size_lines = 0; info.header.npolygons = 6; info.header.size_polygons = 6 * ((4+1) * sizeof(igtl_float32)); info.header.ntriangle_strips = 0; info.header.size_triangle_strips = 0; info.header.nattributes = 1; if (igtl_polydata_alloc_info(&info) == 0) { return EXIT_FAILURE; } /*** Substitute cube point data ***/ if (info.points) { ptr_f = info.points; for (i = 0; i < info.header.npoints; i ++) { *(ptr_f++) = points[i][0]; *(ptr_f++) = points[i][1]; *(ptr_f++) = points[i][2]; } } else { return EXIT_FAILURE; } /*** Substitute polygon data ***/ if (info.polygons) { ptr_i = info.polygons; for (i = 0; i < info.header.npolygons; i ++) { *(ptr_i++) = 4; /* Number of points in the polygon */ *(ptr_i++) = poly[i][0]; *(ptr_i++) = poly[i][1]; *(ptr_i++) = poly[i][2]; *(ptr_i++) = poly[i][3]; } } /*** Substitute attribute data ***/ if (info.attributes) { info.attributes[0].type = IGTL_POLY_ATTR_TYPE_SCALAR; info.attributes[0].ncomponents = 1; info.attributes[0].n = 8; info.attributes[0].name = malloc(5); strcpy(info.attributes[0].name, "attr"); info.attributes[0].data = malloc(sizeof(igtl_float32) * 8); ptr_f = info.attributes[0].data; for (i = 0; i < 8; i ++) { *(ptr_f++) = attribute[i]; } } /** Allocate memory for pack **/ body_size = igtl_polydata_get_size(&info, IGTL_TYPE_PREFIX_NONE); body = malloc((igtl_uint32)body_size); if (body == NULL) { igtl_polydata_free_info(&info); return EXIT_FAILURE; } igtl_polydata_pack(&info, body, IGTL_TYPE_PREFIX_NONE); /*** Set OpenIGTLink header ***/ header.version = 1; strncpy( (char*)&(header.name), "POLYDATA", 12 ); strncpy( (char*)&(header.device_name), "DeviceName", 20 ); header.timestamp = 1234567890; header.body_size = body_size; header.crc = igtl_polydata_get_crc(&info, IGTL_TYPE_PREFIX_NONE, body); igtl_header_convert_byte_order( &(header) ); /* Dumping data -- for testing */ /* FILE *fp; fp = fopen("polydata.bin", "w"); fwrite(&(header), IGTL_HEADER_SIZE, 1, fp); fwrite(body, body_size, 1, fp); fclose(fp); */ rh = memcmp((const void*)&header, (const void*)test_polydata_message_header, IGTL_HEADER_SIZE); rb = memcmp((const void*)body, (const void*)test_polydata_message_body, (size_t) body_size); igtl_polydata_free_info(&info); free(body); if (rh == 0 && rb == 0) { return EXIT_SUCCESS; } else { /* Print first 256 bytes as HEX values in STDERR for debug */ s = IGTL_HEADER_SIZE + (int)body_size; if (s > 256) { s = 256; } fprintf(stdout, "\n===== First %d bytes of the test message =====\n", s); igtl_message_dump_hex(stdout, (const void*)&header, s); return EXIT_FAILURE; } }