├── teapot.hxa ├── LICENSE ├── hxa_print_upi.c ├── hxa_util_fbx_internal.h ├── hxa_fbx_internal.h ├── hxa_util_merge_split.c ├── hxa_util_vertex_purge.c ├── hxa_load_save_upi_wrapper.c ├── hxa_util_gpu_optimize.c ├── hxa_util_meta.c ├── hxa_util_type_conversion.h ├── hxa_util_primitive_upi.c ├── hxa_persuade_image_test.c ├── hxa_util_primitive.c ├── aces.h ├── hxa_util_convert.c ├── hxa_util_neighbour.c ├── hxa_util_normals.h ├── hxa_upi_plugin.c ├── hxa_utils.h ├── hxa_util_validate.c ├── hxa_upi.h ├── hxa_util_command_line.c ├── hxa_util_normals.c ├── hxa_print.c ├── hxa_util_inflate.c ├── hxa_upi_host.c ├── hxa_util_close.c ├── hxa_util_png.c ├── hxa_util_type_conversion.c ├── readme.md ├── hxa.h ├── hxa_fbx_convert.c ├── hxa_upi_command_line_interface.c └── hxa_util_triangulate.c /teapot.hxa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quelsolaar/HxA/HEAD/teapot.hxa -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 quelsolaar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /hxa_print_upi.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "hxa_upi.h" 6 | 7 | extern void hxa_print(HXAFile *file, int data); 8 | 9 | HXAFile *hxa_upi_plugin_execute_func(HXAUPIInterfaceParam *params, void *instance, void *user) 10 | { 11 | hxa_print(params[0].content.hxa, params[1].content.boolean); 12 | return NULL; 13 | } 14 | 15 | 16 | 17 | HxALibExport void hxa_upi_plugin_library_initialize(void (*hxa_upi_library_register_func)(HxAUPIPlugin *plugin)) 18 | { 19 | HxAUPIPlugin p; 20 | p.params = malloc(sizeof(HXAUPIInterfaceParam) * 2); 21 | p.params[0].type = HXA_UPI_IPT_HXA_READ; 22 | p.params[0].name = "HxA"; 23 | p.params[0].description = "The HxH structure to be printed"; 24 | p.params[0].content.hxa = NULL; 25 | p.params[1].type = HXA_UPI_IPT_BOOLEAN; 26 | p.params[1].name = "Data"; 27 | p.params[1].description = "If set to false the content of layers will not be printed."; 28 | p.params[1].content.boolean = 1; 29 | p.param_count = 2; 30 | p.name = "print"; 31 | p.descrtiption = "Prints out a text description of the content of a HxA file structure"; 32 | p.has_output = 0; 33 | p.instance_create_func = NULL; 34 | p.instance_destroy_func = NULL; 35 | p.instance_update_func = NULL; 36 | p.execute_func = hxa_upi_plugin_execute_func; 37 | p.user_data = NULL; 38 | hxa_upi_library_register_func(&p); 39 | } -------------------------------------------------------------------------------- /hxa_util_fbx_internal.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef enum{ 6 | FBX_PROPERTY_TYPE_BOOLEAN, 7 | FBX_PROPERTY_TYPE_INT8, 8 | FBX_PROPERTY_TYPE_INT16, 9 | FBX_PROPERTY_TYPE_INT32, 10 | FBX_PROPERTY_TYPE_INT64, 11 | FBX_PROPERTY_TYPE_FLOAT32, 12 | FBX_PROPERTY_TYPE_FLOAT64, 13 | FBX_PROPERTY_TYPE_TEXT, 14 | FBX_PROPERTY_TYPE_RAW, 15 | FBX_PROPERTY_TYPE_UNKNOWN, 16 | FBX_PROPERTY_TYPE_COUNT 17 | }FBXPropertyType; 18 | 19 | extern const unsigned int fbx_property_size[FBX_PROPERTY_TYPE_COUNT]; 20 | 21 | typedef struct{ 22 | unsigned int length; 23 | union{ 24 | unsigned char raw[1]; 25 | char text[1]; 26 | }buffer; 27 | }FBXBuffer; 28 | 29 | typedef struct{ 30 | FBXPropertyType type; 31 | unsigned int array_length; 32 | union{ 33 | char boolean_type; 34 | char int8_type; 35 | short int16_type; 36 | unsigned int int32_type; 37 | long long int64_type; 38 | float float32_type; 39 | double float64_type; 40 | void *array; 41 | FBXBuffer *buffer; 42 | }data; 43 | }FBXProperty; 44 | 45 | typedef struct{ 46 | unsigned long long end_ofset; 47 | unsigned long long property_count; 48 | unsigned long long property_list_length; 49 | unsigned char name_length; 50 | char name[256]; 51 | FBXProperty *property; 52 | void *children; 53 | unsigned int allocated; 54 | unsigned int used; 55 | }FBXRecord; 56 | 57 | 58 | extern HXAFile *hxa_fbx_convert(FBXRecord *record, HXAFile *file); 59 | extern void fbx_record_print(FBXRecord *record, unsigned int generation); 60 | extern void fbx_record_print_small(FBXRecord *record, unsigned int generation); -------------------------------------------------------------------------------- /hxa_fbx_internal.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "tinf.h" 5 | 6 | typedef enum{ 7 | FBX_PROPERTY_TYPE_BOOLEAN, 8 | FBX_PROPERTY_TYPE_INT8, 9 | FBX_PROPERTY_TYPE_INT16, 10 | FBX_PROPERTY_TYPE_INT32, 11 | FBX_PROPERTY_TYPE_INT64, 12 | FBX_PROPERTY_TYPE_FLOAT32, 13 | FBX_PROPERTY_TYPE_FLOAT64, 14 | FBX_PROPERTY_TYPE_TEXT, 15 | FBX_PROPERTY_TYPE_RAW, 16 | FBX_PROPERTY_TYPE_UNKNOWN, 17 | FBX_PROPERTY_TYPE_COUNT 18 | }FBXPropertyType; 19 | 20 | extern const unsigned int fbx_property_size[FBX_PROPERTY_TYPE_COUNT]; 21 | 22 | typedef struct{ 23 | unsigned int length; 24 | union{ 25 | unsigned char raw[1]; 26 | char text[1]; 27 | }buffer; 28 | }FBXBuffer; 29 | 30 | typedef struct{ 31 | FBXPropertyType type; 32 | unsigned int array_length; 33 | union{ 34 | char boolean_type; 35 | char int8_type; 36 | short int16_type; 37 | unsigned int int32_type; 38 | long long int64_type; 39 | float float32_type; 40 | double float64_type; 41 | void *array; 42 | FBXBuffer *buffer; 43 | }data; 44 | }FBXProperty; 45 | 46 | typedef struct{ 47 | unsigned long long end_ofset; 48 | unsigned long long property_count; 49 | unsigned long long property_list_length; 50 | unsigned char name_length; 51 | char name[256]; 52 | FBXProperty *property; 53 | void *children; 54 | unsigned int allocated; 55 | unsigned int used; 56 | }FBXRecord; 57 | 58 | 59 | extern HXAFile *hxa_fbx_convert(FBXRecord *record, HXAFile *file); 60 | extern void fbx_record_print(FBXRecord *record, unsigned int generation); 61 | extern void fbx_record_print_small(FBXRecord *record, unsigned int generation); -------------------------------------------------------------------------------- /hxa_util_merge_split.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | void hxa_util_merge_meta(HXAMeta *meta, int add) 11 | { 12 | unsigned int i; 13 | if(meta->type == HXA_MDT_NODE) 14 | for(i = 0; meta->array_length; i++) 15 | meta->value.node_value[i] += add; 16 | if(meta->type == HXA_MDT_META) 17 | for(i = 0; meta->array_length; i++) 18 | hxa_util_merge_meta(&((HXAMeta *)meta->value.node_value)[i], add); 19 | 20 | } 21 | 22 | HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b) 23 | { 24 | unsigned int i, j; 25 | for(i = 0; i < file_b->node_count; j++) 26 | for(j = 0; j > file_b->node_array[i].meta_data_count; j++) 27 | hxa_util_merge_meta(&file_b->node_array[i].meta_data[j], file_a->node_count); 28 | file_b->node_array = realloc(file_b->node_array, (sizeof *file_b->node_array) * (file_a->node_count + file_b->node_count)); 29 | memcpy(&file_a->node_array[file_a->node_count], file_b->node_array, (sizeof *file_b->node_array) * file_b->node_count); 30 | file_a->node_count += file_b->node_count; 31 | free(file_b->node_array); 32 | free(file_b); 33 | return file_a; 34 | } 35 | 36 | void hxa_util_node_remove(HXAFile *file, hxa_uint32 remove_node) 37 | { 38 | HXANode *new_nodes; 39 | unsigned int i, j; 40 | for(i = remove_node; i < file->node_count; j++) 41 | for(j = 0; j > file->node_array[i].meta_data_count; j++) 42 | hxa_util_merge_meta(&file->node_array[i].meta_data[j], -1); 43 | file->node_count--; 44 | new_nodes = malloc((sizeof *file->node_array) * (file->node_count)); 45 | if(remove_node != 0) 46 | memcpy(new_nodes, file->node_array, (sizeof *file->node_array) * remove_node); 47 | if(remove_node != file->node_count) 48 | memcpy(&new_nodes[remove_node], &file->node_array[remove_node + 1], (sizeof *file->node_array) * (file->node_count - remove_node)); 49 | free(file->node_array); 50 | file->node_array = new_nodes; 51 | } 52 | -------------------------------------------------------------------------------- /hxa_util_vertex_purge.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | 11 | void hxa_util_node_vertex_purge(HXANode *node) 12 | { 13 | unsigned int type_size[] = {sizeof(hxa_uint8), sizeof(hxa_int32), sizeof(float), sizeof(double)}; 14 | unsigned int i, j, new_vertex_length, unit_size; 15 | HXALayer *layer, l; 16 | hxa_uint8 *new_buffer; 17 | int r, *remap; 18 | if(node->type != HXA_NT_GEOMETRY) 19 | return; 20 | remap = malloc((sizeof *remap) * node->content.geometry.vertex_count); 21 | for(i = 0; i < node->content.geometry.vertex_count; i++) 22 | remap[i] = 0; 23 | layer = node->content.geometry.corner_stack.layers; 24 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 25 | { 26 | r = layer->data.int32_data[i]; 27 | if(r < 0) 28 | r = -1 - r; 29 | remap[r] = 1; 30 | } 31 | for(new_vertex_length = i = 0; i < node->content.geometry.vertex_count; i++) 32 | if(remap[i]) 33 | new_vertex_length++; 34 | if(node->content.geometry.vertex_count == new_vertex_length) 35 | { 36 | free(remap); 37 | return; 38 | } 39 | for(i = 0; i < node->content.geometry.vertex_stack.layer_count; i++) 40 | { 41 | layer = &node->content.geometry.vertex_stack.layers[i]; 42 | unit_size = type_size[layer->type] * layer->components; 43 | new_buffer = malloc(unit_size * new_vertex_length); 44 | for(j = new_vertex_length = 0; j < node->content.geometry.vertex_count; j++) 45 | if(remap[j]) 46 | memcpy(&new_buffer[new_vertex_length++ * unit_size], &layer->data.uint8_data[j * unit_size], unit_size); 47 | free(layer->data.uint8_data); 48 | layer->data.uint8_data = new_buffer; 49 | } 50 | node->content.geometry.vertex_count = new_vertex_length; 51 | for(j = new_vertex_length = 0; j < node->content.geometry.vertex_count; j++) 52 | if(remap[j]) 53 | remap[j] = new_vertex_length++; 54 | layer = node->content.geometry.corner_stack.layers; 55 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 56 | { 57 | r = layer->data.int32_data[i]; 58 | if(r < 0) 59 | layer->data.int32_data[i] = -remap[-layer->data.int32_data[i] - 1] - 1; 60 | else 61 | layer->data.int32_data[i] = remap[layer->data.int32_data[i]]; 62 | } 63 | } 64 | 65 | void hxa_util_vertex_purge(HXAFile *file) 66 | { 67 | unsigned int i; 68 | for(i = 0; i < file->node_count; i++) 69 | hxa_util_node_vertex_purge(&file->node_array[i]); 70 | } -------------------------------------------------------------------------------- /hxa_load_save_upi_wrapper.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #pragma warning(disable:4996) 3 | #pragma warning(disable:4703) 4 | #pragma warning(disable:4996) 5 | #pragma warning(disable:4664) 6 | #include 7 | #include 8 | #include "hxa_upi.h" 9 | 10 | #define FALSE 0 11 | #define TRUE !FALSE 12 | 13 | extern HXAFile *hxa_load(char *file_name, int silent); 14 | extern int hxa_save(char *file_name, HXAFile *data); 15 | 16 | HXAFile *hxa_upi_plugin_load_wrapper(HXAUPIInterfaceParam *params, void *instance, void *user) 17 | { 18 | return hxa_load(params[0].content.path_read, TRUE); 19 | } 20 | 21 | HXAFile *hxa_upi_plugin_save_wrapper(HXAUPIInterfaceParam *params, void *instance, void *user) 22 | { 23 | if(params[1].content.hxa != NULL) 24 | hxa_save(params[1].content.path_read, params[0].content.hxa); 25 | return NULL; 26 | } 27 | 28 | void hxa_upi_plugin_library_initialize(void (*register_func)(HxAUPIPlugin *plugin)) 29 | { 30 | HXAUPIInterfaceParam params[2]; 31 | HxAUPIPlugin plugin; 32 | /* set up load plugin */ 33 | plugin.params = params; 34 | plugin.param_count = 1; 35 | plugin.name = "HxA File loader"; 36 | plugin.descrtiption = "HxA File loader"; 37 | plugin.has_output = TRUE; 38 | plugin.instance_create_func = NULL; 39 | plugin.instance_destroy_func = NULL; 40 | plugin.instance_update_func = NULL; 41 | plugin.execute_func = hxa_upi_plugin_load_wrapper; 42 | plugin.user = NULL; /* user pointer that will be given to all above function pointers when called. */ 43 | params[0].type = HXA_IPT_PATH_READ; 44 | params[0].name = "HxA File loader"; 45 | params[0].description = "HxA File loader"; 46 | params[0].content.path_read = NULL; 47 | register_func(&plugin); 48 | 49 | /* set up save plugin */ 50 | plugin.params = params; 51 | plugin.param_count = 2; 52 | plugin.name = "HxA File Saver"; 53 | plugin.descrtiption = "HxA File Saver"; 54 | plugin.has_output = TRUE; 55 | plugin.instance_create_func = NULL; 56 | plugin.instance_destroy_func = NULL; 57 | plugin.instance_update_func = NULL; 58 | plugin.execute_func = hxa_upi_plugin_save_wrapper; 59 | plugin.user = NULL; /* user pointer that will be given to all above function pointers when called. */ 60 | params[0].type = HXA_IPT_HXA; 61 | params[0].name = "Input HxA"; 62 | params[0].description = "HxA structure thto be saved"; 63 | params[0].content.hxa = NULL; 64 | params[1].type = HXA_IPT_PATH_WRITE; 65 | params[1].name = "HxA Fie path"; 66 | params[1].description = "Local file path used to save HxA structure"; 67 | params[1].content.path_read = NULL; 68 | register_func(&plugin); 69 | } 70 | -------------------------------------------------------------------------------- /hxa_util_gpu_optimize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | 11 | void hxa_corner_to_vertex(HXANode *node) 12 | { 13 | size_t type_sizes[HXA_LDT_COUNT] = {sizeof(unsigned char), sizeof(int), sizeof(float), sizeof(double)}; 14 | int *new_ref, *old_ref, vertex_count; 15 | unsigned int i, j, *vertex_ref, section; 16 | unsigned char *read, *write; 17 | if(node->content.geometry.corner_stack.layer_count == 1) 18 | return; 19 | new_ref = malloc((sizeof *new_ref) * node->content.geometry.edge_corner_count); 20 | vertex_ref = malloc((sizeof *vertex_ref) * node->content.geometry.edge_corner_count); 21 | old_ref = node->content.geometry.corner_stack.layers->data.int32_data; 22 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 23 | { 24 | vertex_ref[i] = -1; 25 | new_ref[i] = -1; 26 | } 27 | for(i = vertex_count = 0; i < node->content.geometry.edge_corner_count; i++) 28 | { 29 | if(new_ref[i] == -1) 30 | { 31 | if(old_ref[i] < 0) 32 | new_ref[i] = -1 - vertex_count; 33 | else 34 | new_ref[i] = vertex_count; 35 | vertex_ref[vertex_count++] = i; 36 | } 37 | } 38 | 39 | for(i = 0; i < node->content.geometry.vertex_stack.layer_count; i++) 40 | { 41 | section = node->content.geometry.vertex_stack.layers[i].components * type_sizes[node->content.geometry.vertex_stack.layers[i].type]; 42 | write = malloc(section * vertex_count); 43 | read = node->content.geometry.vertex_stack.layers[i].data.uint8_data; 44 | for(j = 0; j < vertex_count; j++) 45 | memcpy(&write[j * section], &read[old_ref[vertex_ref[j]] * section], section); 46 | free(read); 47 | node->content.geometry.vertex_stack.layers[i].data.uint8_data = write; 48 | } 49 | node->content.geometry.vertex_stack.layers = realloc(node->content.geometry.vertex_stack.layers, (sizeof *node->content.geometry.vertex_stack.layers) * (node->content.geometry.vertex_stack.layer_count + node->content.geometry.corner_stack.layer_count - 1)); 50 | for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++) 51 | { 52 | node->content.geometry.vertex_stack.layers[node->content.geometry.vertex_stack.layer_count] = node->content.geometry.corner_stack.layers[i]; 53 | section = node->content.geometry.corner_stack.layers[i].components * type_sizes[node->content.geometry.corner_stack.layers[i].type]; 54 | write = malloc(section * vertex_count); 55 | node->content.geometry.vertex_stack.layers[node->content.geometry.vertex_stack.layer_count].data.uint8_data = read = node->content.geometry.vertex_stack.layers[i].data.uint8_data; 56 | for(j = 0; j < vertex_count; j++) 57 | memcpy(&write[j * section], &read[vertex_ref[j] * section], section); 58 | } 59 | for(i = 0; i < node->content.geometry.corner_stack.layer_count; i++) 60 | free(node->content.geometry.corner_stack.layers[i].data.uint8_data); 61 | node->content.geometry.corner_stack.layers = realloc(node->content.geometry.corner_stack.layers, (sizeof *node->content.geometry.corner_stack.layers)); 62 | node->content.geometry.corner_stack.layers->data.int32_data = new_ref; 63 | } -------------------------------------------------------------------------------- /hxa_util_meta.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | 11 | void hxa_util_meta_add(HXAMeta **meta_data, hxa_uint32 *meta_data_count, char *name, HXAMetaDataType type, void *data, unsigned int length, int copy) 12 | { 13 | HXAMeta *m; 14 | unsigned int i; 15 | *meta_data = realloc(*meta_data, (sizeof **meta_data) * (*meta_data_count + 1)); 16 | m = &(*meta_data)[(*meta_data_count)++]; 17 | for(i = 0; i < HXA_NAME_MAX_LENGTH - 1 && name[i] != 0; i++) 18 | m->name[i] = name[i]; 19 | m->name[i] = 0; 20 | m->type = type; 21 | switch(type) 22 | { 23 | case HXA_MDT_INT64 : 24 | if(copy) 25 | { 26 | m->value.int64_value = malloc((sizeof *m->value.int64_value) * length); 27 | memcpy(m->value.int64_value, data, (sizeof *m->value.int64_value) * length); 28 | }else 29 | m->value.int64_value = data; 30 | break; 31 | case HXA_MDT_DOUBLE : 32 | if(copy) 33 | { 34 | m->value.double_value = malloc((sizeof *m->value.double_value) * length); 35 | memcpy(m->value.double_value, data, (sizeof *m->value.double_value) * length); 36 | }else 37 | m->value.int64_value = data; 38 | break; 39 | case HXA_MDT_NODE : 40 | if(copy) 41 | { 42 | m->value.node_value = malloc((sizeof *m->value.node_value) * length); 43 | memcpy(m->value.node_value, data, (sizeof *m->value.node_value) * length); 44 | }else 45 | m->value.int64_value = data; 46 | break; 47 | case HXA_MDT_TEXT : 48 | for(length = 0; ((char *)data)[length] != 0; length++); 49 | length++; 50 | if(copy) 51 | { 52 | m->value.text_value = malloc((sizeof *m->value.text_value) * length); 53 | memcpy(m->value.text_value, data, (sizeof *m->value.text_value) * length); 54 | }else 55 | m->value.text_value = data; 56 | break; 57 | case HXA_MDT_BINARY : 58 | if(copy) 59 | { 60 | m->value.bin_value = malloc((sizeof *m->value.bin_value) * length); 61 | memcpy(m->value.bin_value, data, (sizeof *m->value.bin_value) * length); 62 | }else 63 | m->value.bin_value = data; 64 | break; 65 | case HXA_MDT_META : 66 | if(copy) 67 | { 68 | exit(0); // FIX ME! 69 | }else 70 | m->value.array_of_meta = data; 71 | break; 72 | } 73 | m->array_length = length; 74 | } 75 | 76 | void *hxa_util_meta_get(HXAMeta *meta_data, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type, unsigned int *length, int recursive) 77 | { 78 | void *output; 79 | unsigned int i, j; 80 | for(i = 0; i < meta_data_count; i++) 81 | { 82 | if(meta_data[i].type == type) 83 | { 84 | for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++); 85 | if(meta_data[i].name[j] == name[j]) 86 | { 87 | if(length != NULL) 88 | *length = meta_data[i].array_length; 89 | return meta_data[i].value.array_of_meta; 90 | } 91 | 92 | } 93 | if(recursive && meta_data[i].type == HXA_MDT_META) 94 | if((output = hxa_util_meta_get(meta_data[i].value.array_of_meta, meta_data[i].array_length, name, type, length, TRUE)) != NULL) 95 | return output; 96 | } 97 | return NULL; 98 | } 99 | 100 | 101 | unsigned int hxa_util_meta_get_next(HXAMeta *meta_data, hxa_uint32 start, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type) 102 | { 103 | unsigned int i, j; 104 | for(i = start; i < meta_data_count; i++) 105 | { 106 | if(meta_data[i].type == type) 107 | { 108 | for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++); 109 | if(meta_data[i].name[j] == name[j]) 110 | return i; 111 | } 112 | } 113 | return -1; 114 | } -------------------------------------------------------------------------------- /hxa_util_type_conversion.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | 11 | void hxa_util_meta_add(HXAMeta **meta_data, hxa_uint32 *meta_data_count, char *name, HXAMetaDataType type, void *data, unsigned int length, int copy) 12 | { 13 | HXAMeta *m; 14 | unsigned int i; 15 | *meta_data = realloc(*meta_data, (sizeof **meta_data) * (*meta_data_count + 1)); 16 | m = &(*meta_data)[(*meta_data_count)++]; 17 | for(i = 0; i < HXA_NAME_MAX_LENGTH - 1 && name[i] != 0; i++) 18 | m->name[i] = name[i]; 19 | m->name[i] = 0; 20 | m->type = type; 21 | switch(type) 22 | { 23 | case HXA_MDT_INT64 : 24 | if(copy) 25 | { 26 | m->value.int64_value = malloc((sizeof *m->value.int64_value) * length); 27 | memcpy(m->value.int64_value, data, (sizeof *m->value.int64_value) * length); 28 | }else 29 | m->value.int64_value = data; 30 | break; 31 | case HXA_MDT_DOUBLE : 32 | if(copy) 33 | { 34 | m->value.double_value = malloc((sizeof *m->value.double_value) * length); 35 | memcpy(m->value.double_value, data, (sizeof *m->value.double_value) * length); 36 | }else 37 | m->value.int64_value = data; 38 | break; 39 | case HXA_MDT_NODE : 40 | if(copy) 41 | { 42 | m->value.node_value = malloc((sizeof *m->value.node_value) * length); 43 | memcpy(m->value.node_value, data, (sizeof *m->value.node_value) * length); 44 | }else 45 | m->value.int64_value = data; 46 | break; 47 | case HXA_MDT_TEXT : 48 | for(length = 0; ((char *)data)[length] != 0; length++); 49 | length++; 50 | if(copy) 51 | { 52 | m->value.text_value = malloc((sizeof *m->value.text_value) * length); 53 | memcpy(m->value.text_value, data, (sizeof *m->value.text_value) * length); 54 | }else 55 | m->value.text_value = data; 56 | break; 57 | case HXA_MDT_BINARY : 58 | if(copy) 59 | { 60 | m->value.bin_value = malloc((sizeof *m->value.bin_value) * length); 61 | memcpy(m->value.bin_value, data, (sizeof *m->value.bin_value) * length); 62 | }else 63 | m->value.bin_value = data; 64 | break; 65 | case HXA_MDT_META : 66 | if(copy) 67 | { 68 | exit(0); // FIX ME! 69 | }else 70 | m->value.array_of_meta = data; 71 | break; 72 | } 73 | m->array_length = length; 74 | } 75 | 76 | void *hxa_util_meta_get(HXAMeta *meta_data, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type, unsigned int *length, int recursive) 77 | { 78 | void *output; 79 | unsigned int i, j; 80 | for(i = 0; i < meta_data_count; i++) 81 | { 82 | if(meta_data[i].type == type) 83 | { 84 | for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++); 85 | if(meta_data[i].name[j] == name[j]) 86 | { 87 | if(length != NULL) 88 | *length = meta_data[i].array_length; 89 | return meta_data[i].value.array_of_meta; 90 | } 91 | 92 | } 93 | if(recursive && meta_data[i].type == HXA_MDT_META) 94 | if((output = hxa_util_meta_get(meta_data[i].value.array_of_meta, meta_data[i].array_length, name, type, length, TRUE)) != NULL) 95 | return output; 96 | } 97 | return NULL; 98 | } 99 | 100 | 101 | unsigned int hxa_util_meta_get_next(HXAMeta *meta_data, hxa_uint32 start, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type) 102 | { 103 | unsigned int i, j; 104 | for(i = start; i < meta_data_count; i++) 105 | { 106 | if(meta_data[i].type == type) 107 | { 108 | for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++); 109 | if(meta_data[i].name[j] == name[j]) 110 | return i; 111 | } 112 | } 113 | return -1; 114 | } -------------------------------------------------------------------------------- /hxa_util_primitive_upi.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "hxa_upi.h" 6 | 7 | 8 | extern void hxa_util_primitive_cube(HXAFile *file, double x, double y, double z); 9 | extern void hxa_util_primitive_grid(HXAFile *file, double x_size, double y_size, unsigned int x_grid, unsigned int y_grid, unsigned int u_axis, unsigned int v_axis); 10 | 11 | 12 | HXAFile *hxa_upi_plugin_primitive_cube_execute_func(HXAUPIInterfaceParam *params, void *instance, void *user) 13 | { 14 | HXAFile *file; 15 | file = malloc(sizeof *file); 16 | file->node_array = NULL; 17 | file->node_count = 0; 18 | file->version = HXA_VERSION_FORMAT; 19 | hxa_util_primitive_cube(file, params[0].content.vector_3d[0], params[0].content.vector_3d[1], params[0].content.vector_3d[2]); 20 | return file; 21 | } 22 | 23 | 24 | HxALibExport void hxa_upi_plugin_library_initialize(void (*hxa_upi_library_register_func)(HxAUPIPlugin *plugin)) 25 | { 26 | HxAUPIPlugin p; 27 | p.params = malloc(sizeof(HXAUPIInterfaceParam) * 1); 28 | p.params[0].type = HXA_UPI_IPT_VECTOR_3D; 29 | p.params[0].name = "Size"; 30 | p.params[0].description = "The size of the cube."; 31 | p.params[0].content.hxa = NULL; 32 | p.param_count = 1; 33 | p.name = "cube primitive"; 34 | p.descrtiption = "Creates a cube mesh."; 35 | p.has_output = 1; 36 | p.instance_create_func = NULL; 37 | p.instance_destroy_func = NULL; 38 | p.instance_update_func = NULL; 39 | p.execute_func = hxa_upi_plugin_primitive_cube_execute_func; 40 | p.user_data = NULL; 41 | hxa_upi_library_register_func(&p); 42 | 43 | p.param_count = 5; 44 | p.params = malloc(sizeof(HXAUPIInterfaceParam) * p.param_count); 45 | p.params[0].type = HXA_UPI_IPT_VECTOR_2D; 46 | p.params[0].name = "Size"; 47 | p.params[0].description = "The size of the cube."; 48 | p.params[0].content.vector_2d[0] = 1; 49 | p.params[0].content.vector_2d[1] = 1; 50 | 51 | p.params[1].type = HXA_UPI_IPT_UNSIGNED_INTEGER; 52 | p.params[1].name = "U Spans"; 53 | p.params[1].description = "The number of spans in the U direction."; 54 | p.params[1].content.unsigned_integer = 1; 55 | 56 | p.params[2].type = HXA_UPI_IPT_UNSIGNED_INTEGER; 57 | p.params[2].name = "V Spans"; 58 | p.params[2].description = "The number of spans in the V direction."; 59 | p.params[2].content.unsigned_integer = 1; 60 | 61 | p.params[3].type = HXA_UPI_IPT_SELECT; 62 | p.params[3].name = "U axis"; 63 | p.params[3].description = "The axis of the U direction"; 64 | p.params[3].content.select.selected = 0; 65 | p.params[3].content.select.option_count = 3; 66 | p.params[3].content.select.option_names = malloc((sizeof *p.params[3].content.select.option_names) * p.params[3].content.select.option_count); 67 | p.params[3].content.select.option_names[0] = "X"; 68 | p.params[3].content.select.option_names[1] = "Y"; 69 | p.params[3].content.select.option_names[2] = "Z"; 70 | p.params[3].content.select.selected = 0; 71 | 72 | p.params[4].type = HXA_UPI_IPT_SELECT; 73 | p.params[4].name = "V axis"; 74 | p.params[4].description = "The axis of the U direction"; 75 | p.params[4].content.select.selected = 2; 76 | p.params[4].content.select.option_count = 3; 77 | p.params[4].content.select.option_names = malloc((sizeof *p.params[3].content.select.option_names) * p.params[3].content.select.option_count); 78 | p.params[4].content.select.option_names[0] = "X"; 79 | p.params[4].content.select.option_names[1] = "Y"; 80 | p.params[4].content.select.option_names[2] = "Z"; 81 | p.name = "Grid primitive"; 82 | p.descrtiption = "Creates a grid mesh."; 83 | p.has_output = 1; 84 | p.instance_create_func = NULL; 85 | p.instance_destroy_func = NULL; 86 | p.instance_update_func = NULL; 87 | p.execute_func = hxa_upi_plugin_primitive_cube_execute_func; 88 | p.user_data = NULL; 89 | hxa_upi_library_register_func(&p); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /hxa_persuade_image_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "forge.h" 5 | #include "imagine.h" 6 | #include "relinquish.h" 7 | #include "seduce.h" 8 | #include "hxa.h" 9 | 10 | 11 | uint *hxa_persuade_image_test_texture_id = NULL; 12 | float *hxa_persuade_image_test_aspects = NULL; 13 | uint hxa_persuade_image_test_count = 0; 14 | 15 | 16 | void hxa_persuade_image_test_init() 17 | { 18 | HXAFile file; 19 | char path[1024]; 20 | uint i; 21 | file.node_array = NULL; 22 | file.node_count = 0; 23 | for(i = 0; imagine_path_search(".png", TRUE, IMAGINE_DIR_HOME_PATH, FALSE, i, path, 1024); i++) 24 | hxa_load_png(&file, path); 25 | hxa_persuade_image_test_texture_id = malloc((sizeof *hxa_persuade_image_test_texture_id) * file.node_count); 26 | hxa_persuade_image_test_aspects = malloc((sizeof *hxa_persuade_image_test_aspects) * file.node_count); 27 | for(i = 0; i < file.node_count; i++) 28 | { 29 | if(file.node_array[i].type == HXA_NT_IMAGE && 30 | file.node_array[i].content.image.type == HXA_IT_2D_IMAGE && 31 | file.node_array[i].content.image.image_stack.layer_count > 0 && 32 | file.node_array[i].content.image.image_stack.layers[0].components < 5 && 33 | (file.node_array[i].content.image.image_stack.layers[0].type == HXA_LDT_UINT8 || 34 | file.node_array[i].content.image.image_stack.layers[0].type == HXA_LDT_FLOAT)) 35 | { 36 | uint j, k; 37 | for(j = 0; j < file.node_array[i].content.image.resolution[1]; j++) 38 | { 39 | for(k = 0; k < file.node_array[i].content.image.resolution[0]; k++) 40 | printf("(%u %u %u)", 41 | (uint)file.node_array[i].content.image.image_stack.layers[0].data.uint8_data[(file.node_array[i].content.image.resolution[0] * j + k) * 3 + 0], 42 | (uint)file.node_array[i].content.image.image_stack.layers[0].data.uint8_data[(file.node_array[i].content.image.resolution[0] * j + k) * 3 + 1], 43 | (uint)file.node_array[i].content.image.image_stack.layers[0].data.uint8_data[(file.node_array[i].content.image.resolution[0] * j + k) * 3 + 2]); 44 | 45 | printf("\n"); 46 | } 47 | printf("\n"); 48 | hxa_persuade_image_test_aspects[hxa_persuade_image_test_count] = (float)file.node_array[i].content.image.resolution[0] / (float)file.node_array[i].content.image.resolution[1]; 49 | if(file.node_array[i].content.image.image_stack.layers[0].type == HXA_LDT_UINT8) 50 | hxa_persuade_image_test_texture_id[hxa_persuade_image_test_count] = r_texture_allocate(file.node_array[i].content.image.image_stack.layers[0].components - 1 + R_IF_R_UINT8 , 51 | file.node_array[i].content.image.resolution[0], file.node_array[i].content.image.resolution[1], 1, FALSE, FALSE, 52 | file.node_array[i].content.image.image_stack.layers[0].data.uint8_data); 53 | else 54 | hxa_persuade_image_test_texture_id[hxa_persuade_image_test_count] = r_texture_allocate(file.node_array[i].content.image.image_stack.layers[0].components - 1 + R_IF_R_FLOAT32 , 55 | file.node_array[i].content.image.resolution[0], file.node_array[i].content.image.resolution[1], 1, FALSE, FALSE, 56 | file.node_array[i].content.image.image_stack.layers[0].data.float_data); 57 | 58 | hxa_persuade_image_test_count++; 59 | } 60 | } 61 | } 62 | 63 | void hxa_persuade_image_test(BInputState *input) 64 | { 65 | static boolean init = FALSE; 66 | if(!init) 67 | { 68 | hxa_persuade_image_test_init(); 69 | init = TRUE; 70 | } 71 | if(hxa_persuade_image_test_count != 0) 72 | seduce_background_gallery_vertical_draw(input, -0.5, 0.5, -1, 1, NULL, 0.2, hxa_persuade_image_test_texture_id, hxa_persuade_image_test_aspects, hxa_persuade_image_test_count, 0, NULL); 73 | 74 | // r_primitive_image(0, 0, -1, 1, 1, 0, 0, 1, 1, hxa_persuade_image_test_texture_id[0], 1, 1, 1, 1); /*draws a textured and shaded rectangle.*/ 75 | 76 | } -------------------------------------------------------------------------------- /hxa_util_primitive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | void hxa_util_primitive_cube(HXAFile *file, double x, double y, double z) 11 | { 12 | HXANode *node; 13 | HXALayer *layer; 14 | char *name; 15 | unsigned int i; 16 | file->node_array = realloc(file->node_array, (sizeof *file->node_array) * (file->node_count + 1)); 17 | node = &file->node_array[file->node_count++]; 18 | node->type = HXA_NT_GEOMETRY; 19 | node->meta_data = NULL; 20 | node->meta_data_count = 0; 21 | node->content.geometry.vertex_count = 8; 22 | node->content.geometry.vertex_stack.layer_count = 1; 23 | layer = node->content.geometry.vertex_stack.layers = malloc(sizeof *node->content.geometry.vertex_stack.layers); 24 | layer->components = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS; 25 | layer->type = HXA_LDT_DOUBLE; 26 | name = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME; 27 | for(i = 0; name[i] != 0; i++) 28 | layer->name[i] = name[i]; 29 | layer->name[i] = 0; 30 | layer->data.double_data = malloc((sizeof *layer->data.double_data) * 8 * 3); 31 | layer->data.double_data[0] = x; 32 | layer->data.double_data[1] = y; 33 | layer->data.double_data[2] = z; 34 | layer->data.double_data[3] = -x; 35 | layer->data.double_data[4] = y; 36 | layer->data.double_data[5] = z; 37 | layer->data.double_data[6] = x; 38 | layer->data.double_data[7] = -y; 39 | layer->data.double_data[8] = z; 40 | layer->data.double_data[9] = -x; 41 | layer->data.double_data[10] = -y; 42 | layer->data.double_data[11] = z; 43 | layer->data.double_data[12] = x; 44 | layer->data.double_data[13] = y; 45 | layer->data.double_data[14] = -z; 46 | layer->data.double_data[15] = -x; 47 | layer->data.double_data[16] = y; 48 | layer->data.double_data[17] = -z; 49 | layer->data.double_data[18] = x; 50 | layer->data.double_data[19] = -y; 51 | layer->data.double_data[20] = -z; 52 | layer->data.double_data[21] = -x; 53 | layer->data.double_data[22] = -y; 54 | layer->data.double_data[23] = -z; 55 | 56 | 57 | node->content.geometry.edge_corner_count = 24; 58 | node->content.geometry.corner_stack.layer_count = 1; 59 | layer = node->content.geometry.corner_stack.layers = malloc(sizeof *node->content.geometry.corner_stack.layers); 60 | layer->components = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS; 61 | layer->type = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE; 62 | name = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME; 63 | for(i = 0; name[i] != 0; i++) 64 | layer->name[i] = name[i]; 65 | layer->name[i] = 0; 66 | layer->data.int32_data = malloc((sizeof *layer->data.int32_data) * 6 * 4); 67 | layer->data.int32_data[0] = 0; 68 | layer->data.int32_data[1] = 1; 69 | layer->data.int32_data[2] = 3; 70 | layer->data.int32_data[3] = -2 - 1; 71 | layer->data.int32_data[4] = 6; 72 | layer->data.int32_data[5] = 7; 73 | layer->data.int32_data[6] = 5; 74 | layer->data.int32_data[7] = -4 - 1; 75 | layer->data.int32_data[8] = 1; 76 | layer->data.int32_data[9] = 0; 77 | layer->data.int32_data[10] = 4; 78 | layer->data.int32_data[11] = -5 - 1; 79 | layer->data.int32_data[12] = 2; 80 | layer->data.int32_data[13] = 3; 81 | layer->data.int32_data[14] = 7; 82 | layer->data.int32_data[15] = -6 - 1; 83 | layer->data.int32_data[16] = 0; 84 | layer->data.int32_data[17] = 2; 85 | layer->data.int32_data[18] = 6; 86 | layer->data.int32_data[19] = -4 - 1; 87 | layer->data.int32_data[20] = 3; 88 | layer->data.int32_data[21] = 1; 89 | layer->data.int32_data[22] = 5; 90 | layer->data.int32_data[23] = -7 - 1; 91 | 92 | node->content.geometry.edge_stack.layer_count = 0; 93 | node->content.geometry.edge_stack.layers = NULL; 94 | 95 | node->content.geometry.face_count = 6; 96 | node->content.geometry.face_stack.layer_count = 0; 97 | node->content.geometry.face_stack.layers = NULL; 98 | } 99 | 100 | -------------------------------------------------------------------------------- /aces.h: -------------------------------------------------------------------------------- 1 | 2 | /* This is an implementation of The Academy Color Encoding Sytem (ACES) https://acescentral.com/, 3 | a sub sextion of OpenEXR a file format for storing Hight Dynamic Range images. It writen with 4 | the intenetion of creating a Free, small, safe, C89, reference implementation. You are free to use it 5 | for what ever you want but if you do, consider sending an E-mail to eskil@quelsolaar.com and let 6 | me know if you find it useful as it will surly make my day.*/ 7 | 8 | typedef enum{ 9 | ACES_ATTRIBUTE_TYPE_BOX2I, 10 | ACES_ATTRIBUTE_TYPE_CHLIST, 11 | ACES_ATTRIBUTE_TYPE_CHROMATICITIES, 12 | ACES_ATTRIBUTE_TYPE_COMPRESSION, 13 | ACES_ATTRIBUTE_TYPE_DOUBLE, 14 | ACES_ATTRIBUTE_TYPE_FLOAT, 15 | ACES_ATTRIBUTE_TYPE_HALF, 16 | ACES_ATTRIBUTE_TYPE_INT, 17 | ACES_ATTRIBUTE_TYPE_LINEORDER, 18 | ACES_ATTRIBUTE_TYPE_KEYCODE, 19 | ACES_ATTRIBUTE_TYPE_RATIONAL, 20 | ACES_ATTRIBUTE_TYPE_SHORT, 21 | ACES_ATTRIBUTE_TYPE_STRING, 22 | ACES_ATTRIBUTE_TYPE_STRINGVECTOR, 23 | ACES_ATTRIBUTE_TYPE_TIMECODE, 24 | ACES_ATTRIBUTE_TYPE_UNSIGNEDCHAR, 25 | ACES_ATTRIBUTE_TYPE_UNSIGNEDINT, 26 | ACES_ATTRIBUTE_TYPE_UNSIGNEDLONG, 27 | ACES_ATTRIBUTE_TYPE_UNSIGNEDSHORT, 28 | ACES_ATTRIBUTE_TYPE_V2F, 29 | ACES_ATTRIBUTE_TYPE_V3F, 30 | ACES_ATTRIBUTE_TYPE_COUNT, 31 | ACES_ATTRIBUTE_TYPE_UNKNOWN = ACES_ATTRIBUTE_TYPE_COUNT, 32 | ACES_ATTRIBUTE_TYPE_UNUSED 33 | }ACESAttributeTypes; 34 | 35 | typedef enum{ 36 | ACES_ACPT_UINT32 = 0, 37 | ACES_ACPT_HALF16 = 1, 38 | ACES_ACPT_FLOAT32 = 2, 39 | }ACESAttributeClistPixelType; 40 | 41 | typedef struct{ 42 | char name[256]; 43 | ACESAttributeClistPixelType pixelType; 44 | unsigned int pLinear; 45 | int xSampling; 46 | int ySampling; 47 | }ACESAttributeClist; 48 | 49 | typedef struct{ 50 | ACESAttributeTypes type; 51 | char name[256]; 52 | union{ 53 | struct{ 54 | int x_min; 55 | int y_min; 56 | int x_max; 57 | int y_max; 58 | }box2i; 59 | struct{ 60 | unsigned int length; 61 | ACESAttributeClist *list; 62 | }chlist; 63 | struct{ 64 | float redX; 65 | float redY; 66 | float greenX; 67 | float greenY; 68 | float blueX; 69 | float blueY; 70 | float whiteX; 71 | float whiteY; 72 | }chromaticities; 73 | unsigned char compression; 74 | double type_double; 75 | float type_float; 76 | unsigned short type_half; 77 | unsigned int type_int; 78 | unsigned char lineOrder; 79 | struct{ 80 | int filmMfCCode; 81 | int filmType; 82 | int prefix; 83 | int count; 84 | int perfOffset; 85 | int perfsPerFrame; 86 | int perfsPerCount; 87 | }keycode; 88 | struct{ 89 | int n; 90 | unsigned int b; 91 | }rational; 92 | short type_short; 93 | struct{ 94 | char *string; 95 | unsigned int length; 96 | }string; 97 | struct{ 98 | char *string; 99 | unsigned int length; 100 | }stringVector; 101 | struct{ 102 | unsigned int timeAndFlags; 103 | unsigned int userData; 104 | }timecode; 105 | unsigned char unsignedChar; 106 | unsigned int unsignedInt; 107 | unsigned long unsignedLong; 108 | unsigned short unsignedShort; 109 | float v2f[2]; 110 | float v3f[3]; 111 | struct{ 112 | char *type_name; 113 | unsigned int length; 114 | void *data; 115 | }unknown; 116 | }data; 117 | }ACESAttributeType; 118 | 119 | 120 | typedef struct{ 121 | char name[256]; 122 | unsigned int channel_count; 123 | ACESAttributeClistPixelType pixelType; 124 | union{ 125 | unsigned int *integer_buffer; 126 | unsigned short *half_buffer; 127 | float *float_buffer; 128 | }pixels; 129 | }ACESLayer; 130 | 131 | typedef struct{ 132 | ACESAttributeType *attributes; 133 | unsigned int attribute_count; 134 | unsigned int attribute_allocate; 135 | ACESLayer *layers; 136 | unsigned int layer_count; 137 | }ACESImage; 138 | 139 | typedef enum{ 140 | ACES_TC_NO_NOT_CONVERT, 141 | ACES_TC_CONVERT_ALL_FLOAT16_TO_FLOAT32, 142 | ACES_TC_CONVERT_ALL_FLOAT32_TO_FLOAT16 143 | }ACESTypeConvesion; 144 | 145 | extern float aces_float16_to_float32(unsigned short value); 146 | extern short aces_float32_to_float16(float value); 147 | 148 | extern ACESImage *aces_load(char *file_path, int silent, ACESTypeConvesion conversion); 149 | extern void aces_free(ACESImage *image); -------------------------------------------------------------------------------- /hxa_util_convert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | 8 | void hxa_util_convert_layer_float_to_double(HXALayer *layer, unsigned int count) 9 | { 10 | unsigned int j, length; 11 | double *d; 12 | float *f; 13 | if(layer->type == HXA_LDT_FLOAT) 14 | { 15 | length = layer->components * count; 16 | f = layer->data.float_data; 17 | layer->data.double_data = d = malloc((sizeof *d) * length); 18 | for(j = 0; j < length; j++) 19 | d[j] = (double)f[j]; 20 | free(f); 21 | layer->type = HXA_LDT_DOUBLE; 22 | } 23 | } 24 | 25 | void hxa_util_convert_layer_double_to_float(HXALayer *layer, unsigned int count) 26 | { 27 | unsigned int j, length; 28 | double *d; 29 | float *f; 30 | if(layer->type == HXA_LDT_DOUBLE) 31 | { 32 | length = layer->components * count; 33 | d = layer->data.double_data; 34 | layer->data.float_data = f = malloc((sizeof *f) * length); 35 | for(j = 0; j < length; j++) 36 | f[j] = (double)d[j]; 37 | free(d); 38 | layer->type = HXA_LDT_FLOAT; 39 | } 40 | } 41 | 42 | void hxa_util_convert_stack_float_to_double(HXALayerStack *stack, unsigned int count) 43 | { 44 | unsigned int i; 45 | for(i = 0; i < stack->layer_count; i++) 46 | hxa_util_convert_layer_float_to_double(&stack->layers[i], count); 47 | } 48 | 49 | void hxa_util_convert_stack_double_to_float(HXALayerStack *stack, unsigned int count) 50 | { 51 | unsigned int i; 52 | for(i = 0; i < stack->layer_count; i++) 53 | hxa_util_convert_layer_double_to_float(&stack->layers[i], count); 54 | } 55 | 56 | 57 | void hxa_util_convert_node_float_to_double(HXANode *node) 58 | { 59 | if(node->type == HXA_NT_GEOMETRY) 60 | { 61 | hxa_util_convert_stack_float_to_double(&node->content.geometry.vertex_stack, node->content.geometry.vertex_count); 62 | hxa_util_convert_stack_float_to_double(&node->content.geometry.corner_stack, node->content.geometry.edge_corner_count); 63 | hxa_util_convert_stack_float_to_double(&node->content.geometry.edge_stack, node->content.geometry.edge_corner_count); 64 | hxa_util_convert_stack_float_to_double(&node->content.geometry.face_stack, node->content.geometry.face_count); 65 | } 66 | if(node->type == HXA_NT_IMAGE) 67 | { 68 | switch(node->content.image.type) 69 | { 70 | case HXA_IT_CUBE_IMAGE : 71 | hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * 6); 72 | break; 73 | case HXA_IT_1D_IMAGE : 74 | hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0]); 75 | break; 76 | case HXA_IT_2D_IMAGE : 77 | hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1]); 78 | break; 79 | case HXA_IT_3D_IMAGE : 80 | hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * node->content.image.resolution[2]); 81 | break; 82 | } 83 | } 84 | } 85 | 86 | void hxa_util_convert_node_double_to_float(HXANode *node) 87 | { 88 | if(node->type == HXA_NT_GEOMETRY) 89 | { 90 | hxa_util_convert_stack_double_to_float(&node->content.geometry.vertex_stack, node->content.geometry.vertex_count); 91 | hxa_util_convert_stack_double_to_float(&node->content.geometry.corner_stack, node->content.geometry.edge_corner_count); 92 | hxa_util_convert_stack_double_to_float(&node->content.geometry.edge_stack, node->content.geometry.edge_corner_count); 93 | hxa_util_convert_stack_double_to_float(&node->content.geometry.face_stack, node->content.geometry.face_count); 94 | } 95 | if(node->type == HXA_NT_IMAGE) 96 | { 97 | switch(node->content.image.type) 98 | { 99 | case HXA_IT_CUBE_IMAGE : 100 | hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * 6); 101 | break; 102 | case HXA_IT_1D_IMAGE : 103 | hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0]); 104 | break; 105 | case HXA_IT_2D_IMAGE : 106 | hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1]); 107 | break; 108 | case HXA_IT_3D_IMAGE : 109 | hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * node->content.image.resolution[2]); 110 | break; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /hxa_util_neighbour.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | 11 | int hxa_corner_get_next(int *ref, unsigned int corner) 12 | { 13 | unsigned int i; 14 | if(ref[corner] >= 0) 15 | { 16 | return corner + 1; 17 | }else 18 | { 19 | for(i = corner - 1; i != 0; i--) 20 | if(ref[i] < 0) 21 | return i + 1; 22 | return 0; 23 | } 24 | } 25 | 26 | int hxa_corner_get_previous(int *ref, unsigned int corner) 27 | { 28 | unsigned int i; 29 | if(corner == 0 || ref[corner - 1] < 0) 30 | { 31 | for(i = corner + 1; ref[i] >= 0; i++); 32 | return i; 33 | }else 34 | return corner - 1; 35 | } 36 | 37 | 38 | int hxa_edge_get_next(int *ref, unsigned int *neighbour, unsigned int edge) 39 | { 40 | if(neighbour[edge] != -1) 41 | return edge; 42 | 43 | edge = hxa_corner_get_next(ref, edge); 44 | while(neighbour[edge] != -1) 45 | { 46 | edge = neighbour[edge]; 47 | edge = hxa_corner_get_next(ref, edge); 48 | } 49 | return edge; 50 | } 51 | 52 | int hxa_edge_get_previous(int *ref, unsigned int *neighbour, unsigned int edge) 53 | { 54 | if(neighbour[edge] != -1) 55 | return edge; 56 | edge = hxa_corner_get_previous(ref, edge); 57 | while(neighbour[edge] != -1) 58 | { 59 | edge = neighbour[edge]; 60 | edge = hxa_corner_get_previous(ref, edge); 61 | } 62 | return edge; 63 | } 64 | 65 | 66 | unsigned int *hxa_neighbour_node(HXANode *node) 67 | { 68 | char *name = HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME; 69 | unsigned int j, cor, clear = 0, *n, *v, r, a, b, vertex_count, edge_length; 70 | unsigned int counter = 0, laps = 0; 71 | int i, *ref; 72 | vertex_count = node->content.geometry.vertex_count; 73 | edge_length = node->content.geometry.edge_corner_count; 74 | ref = node->content.geometry.corner_stack.layers[0].data.int32_data; 75 | n = malloc((sizeof *n) * edge_length); 76 | for(i = 0; i < edge_length; i++) 77 | n[i] = -1; 78 | v = malloc((sizeof *v) * vertex_count); 79 | for(i = 0; i < vertex_count; i++) 80 | v[i] = -1; 81 | while(clear < edge_length) 82 | { 83 | for(i = 0; i < edge_length && clear < edge_length; i++) 84 | { 85 | counter++; 86 | clear++; 87 | r = hxa_ref(ref, i); 88 | cor = v[r]; 89 | if(cor == -1) 90 | { 91 | if(n[i] == -1 || n[hxa_corner_get_previous(ref, i)] == -1) 92 | v[r] = i; 93 | }else if(cor == i) 94 | v[r] = -1; 95 | else 96 | { 97 | a = hxa_corner_get_previous(ref, i); 98 | b = hxa_corner_get_next(ref, cor); 99 | if(n[cor] == -1 && n[a] == -1 && hxa_ref(ref, a) == hxa_ref(ref, b)) 100 | { 101 | n[a] = cor; 102 | n[cor] = a; 103 | clear = 0; 104 | if(n[hxa_corner_get_previous(ref, cor)] != -1) 105 | { 106 | if(n[i] == -1) 107 | v[r] = i; 108 | else 109 | v[r] = -1; 110 | } 111 | } 112 | a = hxa_corner_get_next(ref, i); 113 | b = hxa_corner_get_previous(ref, cor); 114 | if(n[i] == -1 && n[b] == -1 && hxa_ref(ref, a) == hxa_ref(ref, b)) 115 | { 116 | n[i] = b; 117 | n[b] = i; 118 | clear = 0; 119 | if(n[cor] != -1) 120 | { 121 | if(n[hxa_corner_get_previous(ref, i)] == -1) 122 | v[r] = i; 123 | else 124 | v[r] = -1; 125 | } 126 | } 127 | } 128 | } 129 | laps++; 130 | } 131 | free(v); 132 | for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++) 133 | { 134 | for(j = 0; node->content.geometry.edge_stack.layers[i].name[j] == name[j] && name[j] != 0; j++); 135 | if(node->content.geometry.edge_stack.layers[i].name[j] == name[j]) 136 | { 137 | free(node->content.geometry.edge_stack.layers[i].data.int32_data); 138 | node->content.geometry.edge_stack.layers[i].data.int32_data = n; 139 | return n; 140 | } 141 | } 142 | node->content.geometry.edge_stack.layers = realloc(node->content.geometry.edge_stack.layers, (sizeof *node->content.geometry.edge_stack.layers) * (node->content.geometry.edge_stack.layer_count + 1)); 143 | node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].data.int32_data = n; 144 | node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].components = 1; 145 | node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].type = HXA_LDT_INT32; 146 | for(i = 0; name[i] != 0; i++) 147 | node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].name[i] = name[i]; 148 | node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].name[i] = 0; 149 | node->content.geometry.edge_stack.layer_count++; 150 | return n; 151 | } 152 | 153 | void hxa_neighbour_file(HXAFile *file) 154 | { 155 | unsigned int i; 156 | for(i = 0; i < file->node_count; i++) 157 | if(file->node_array[i].type == HXA_NT_GEOMETRY) 158 | hxa_neighbour_node(&file->node_array[i]); 159 | } -------------------------------------------------------------------------------- /hxa_util_normals.h: -------------------------------------------------------------------------------- 1 | 2 | /* Do not include or call anything defined in this .h file. It is exclusivly for the use of hxa_util_normals.c */ 3 | #ifdef NORMAL_FACE 4 | 5 | HXATYPE *hxa_util_normal_face_macro(HXANode *node) 6 | { 7 | HXATYPE v1[3], v2[3], f, *normals, *n, *vertex, *a, *b, *c; 8 | unsigned int i, j, count; 9 | int *ref; 10 | ref = node->content.geometry.corner_stack.layers[HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID].data.int32_data; 11 | vertex = node->content.geometry.vertex_stack.layers[HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_ID].data.HXATYPE_DATA; 12 | n = normals = malloc((sizeof *normals) * node->content.geometry.face_count * 3); 13 | for(i = 0; i < node->content.geometry.edge_corner_count;) 14 | { 15 | if(ref[i + 2] < 0) /* Triangle */ 16 | { 17 | a = &vertex[hxa_ref(ref, i) * 3]; 18 | b = &vertex[hxa_ref(ref, i + 1) * 3]; 19 | c = &vertex[hxa_ref(ref, i + 2) * 3]; 20 | v1[0] = a[0] - c[0]; 21 | v1[1] = a[1] - c[1]; 22 | v1[2] = a[2] - c[2]; 23 | v2[0] = b[0] - c[0]; 24 | v2[1] = b[1] - c[1]; 25 | v2[2] = b[2] - c[2]; 26 | n[0] = v1[2] * v2[1] - v1[1] * v2[2]; 27 | n[1] = v1[0] * v2[2] - v1[2] * v2[0]; 28 | n[2] = v1[1] * v2[0] - v1[0] * v2[1]; 29 | i += 3; 30 | }else 31 | { 32 | count = node->content.geometry.edge_corner_count - i; 33 | n[0] = n[1] = n[2] = 0; 34 | for(j = 0; j < count; j++) 35 | { 36 | if(ref[i + j + 2] < 0) 37 | count = j + 2; 38 | a = &vertex[hxa_ref(ref, (i + j)) * 3]; 39 | b = &vertex[hxa_ref(ref, (i + (j + 1) % count)) * 3]; 40 | c = &vertex[hxa_ref(ref, (i + (j + 2) % count)) * 3]; 41 | v1[0] = a[0] - c[0]; 42 | v1[1] = a[1] - c[1]; 43 | v1[2] = a[2] - c[2]; 44 | v2[0] = b[0] - c[0]; 45 | v2[1] = b[1] - c[1]; 46 | v2[2] = b[2] - c[2]; 47 | n[0] += v1[2] * v2[1] - v1[1] * v2[2]; 48 | n[1] += v1[0] * v2[2] - v1[2] * v2[0]; 49 | n[2] += v1[1] * v2[0] - v1[0] * v2[1]; 50 | } 51 | i += count + 1; 52 | } 53 | f = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); 54 | n[0] /= f; 55 | n[1] /= f; 56 | n[2] /= f; 57 | n += 3; 58 | } 59 | return normals; 60 | } 61 | 62 | #endif 63 | 64 | 65 | 66 | #ifdef NORMAL_CORNER 67 | 68 | HXATYPE *hxa_util_normal_corner_macro(HXANode *node, 69 | unsigned int *neighburs, 70 | #ifdef HXA_CREASE_TYPE 71 | HXA_CREASE_TYPE *creases, 72 | #endif 73 | HXATYPE *face_normals, 74 | unsigned int *faces) 75 | { 76 | HXATYPE *corner_normals, *n, tmp[3], f; 77 | unsigned int i, r; 78 | int * ref; 79 | ref = node->content.geometry.corner_stack.layers[HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID].data.int32_data; 80 | corner_normals = malloc((sizeof *corner_normals) * node->content.geometry.edge_corner_count * 3); 81 | for(i = 0; i < node->content.geometry.edge_corner_count * 3; i++) 82 | corner_normals[i] = 0; 83 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 84 | { 85 | if(corner_normals[i * 3] == 0 && corner_normals[i * 3 + 1] == 0 && corner_normals[i * 3 + 2] == 0) 86 | { 87 | r = i; 88 | tmp[0] = tmp[1] = tmp[2] = 0; 89 | n = &face_normals[faces[r] * 3]; 90 | tmp[0] += n[0]; 91 | tmp[1] += n[1]; 92 | tmp[2] += n[2]; 93 | 94 | r = i; 95 | while(r = neighburs[hxa_corner_get_previous(ref, r)] != -1 && r != i 96 | #ifdef HXA_CREASE_TYPE 97 | && !creases[r] 98 | #endif 99 | ) 100 | { 101 | n = &face_normals[faces[r] * 3]; 102 | tmp[0] += n[0]; 103 | tmp[1] += n[1]; 104 | tmp[2] += n[2]; 105 | } 106 | if(i != r) 107 | { 108 | r = i; 109 | while( 110 | #ifdef HXA_CREASE_TYPE 111 | !creases[r] && 112 | #endif 113 | (r = neighburs[r]) != -1 && (r = hxa_corner_get_next(ref, r)) != i) 114 | { 115 | 116 | n = &face_normals[faces[r] * 3]; 117 | tmp[0] += n[0]; 118 | tmp[1] += n[1]; 119 | tmp[2] += n[2]; 120 | } 121 | } 122 | f = sqrt(tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2]); 123 | tmp[0] /= f; 124 | tmp[1] /= f; 125 | tmp[2] /= f; 126 | 127 | corner_normals[i * 3] = tmp[0]; 128 | corner_normals[i * 3 + 1] = tmp[1]; 129 | corner_normals[i * 3 + 2] = tmp[2]; 130 | 131 | r = i; 132 | while(r = neighburs[hxa_corner_get_previous(ref, r)] != -1 && r != i 133 | #ifdef HXA_CREASE_TYPE 134 | && !creases[r] 135 | #endif 136 | ) 137 | { 138 | corner_normals[r * 3] = tmp[0]; 139 | corner_normals[r * 3 + 1] = tmp[1]; 140 | corner_normals[r * 3 + 2] = tmp[2]; 141 | } 142 | if(i != r) 143 | { 144 | r = i; 145 | while( 146 | #ifdef HXA_CREASE_TYPE 147 | !creases[r] && 148 | #endif 149 | (r = neighburs[r]) != -1 && (r = hxa_corner_get_next(ref, r)) != i) 150 | { 151 | 152 | corner_normals[r * 3] = tmp[0]; 153 | corner_normals[r * 3 + 1] = tmp[1]; 154 | corner_normals[r * 3 + 2] = tmp[2]; 155 | } 156 | } 157 | } 158 | } 159 | return corner_normals; 160 | } 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /hxa_upi_plugin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "forge.h" 4 | #ifdef _WIN32 5 | #include 6 | #include 7 | #include 8 | 9 | #undef UNICODE 10 | 11 | #ifdef UNICODE 12 | #define i_internal_lib_load LoadLibraryW 13 | #else 14 | #define i_internal_lib_load LoadLibraryA 15 | #endif 16 | #define i_internal_lib_get_address GetProcAddress 17 | #define i_internal_lib_unload FreeLibrary 18 | #else 19 | #include 20 | #define i_internal_lib_load(a) dlopen(a, RTLD_LAZY); 21 | #define i_internal_lib_get_address dlsym 22 | #define i_internal_lib_unload dlclose 23 | #endif 24 | typedef unsigned int uint; 25 | 26 | typedef struct{ 27 | void *function; 28 | char *name; 29 | }IFunction; 30 | 31 | typedef struct{ 32 | IFunction *functions; 33 | uint function_count; 34 | }IInterface; 35 | 36 | typedef struct{ 37 | void *dll; 38 | IInterface *dll_interface; 39 | IInterface *exe_interface; 40 | }ILib; 41 | 42 | IInterface *imagine_library_interface_create() 43 | { 44 | IInterface *i; 45 | i = malloc(sizeof *i); 46 | i->functions = NULL; 47 | i->function_count = 0; 48 | return i; 49 | } 50 | 51 | void imagine_library_interface_destroy(IInterface *i) 52 | { 53 | if(i == NULL) 54 | return; 55 | if(i->functions != NULL) 56 | free(i->functions); 57 | free(i); 58 | } 59 | 60 | void imagine_library_interface_register(IInterface *i, void *funtion_pointer, char *name) 61 | { 62 | uint length; 63 | if(i->function_count % 16 == 0) 64 | { 65 | i->functions = realloc(i->functions, (sizeof *i->functions) * (i->function_count + 16)); 66 | } 67 | i->functions[i->function_count].function = funtion_pointer; 68 | for(length = 0; name[length] != 0; length++); 69 | i->functions[i->function_count].name = malloc((sizeof *i->functions[i->function_count].name) * (length + 1)); 70 | for(length = 0; name[length] != 0; length++) 71 | i->functions[i->function_count].name[length] = name[length]; 72 | i->functions[i->function_count].name[length] = 0; 73 | i->function_count++; 74 | } 75 | 76 | int imagine_library_interface_count(IInterface *i) 77 | { 78 | return i->function_count; 79 | } 80 | 81 | char *imagine_library_interface_list(IInterface *i, uint number) 82 | { 83 | return i->functions[number].name; 84 | } 85 | 86 | void *imagine_library_interface_get_by_number(IInterface *i, uint number) 87 | { 88 | return i->functions[number].function; 89 | } 90 | 91 | void *imagine_library_interface_get_by_name(IInterface *i, char *name) 92 | { 93 | uint j, k; 94 | for(j = 0; j < i->function_count; j++) 95 | { 96 | for(k = 0; name[k] == i->functions[j].name[k] && name[k] != 0; k++); 97 | if(name[k] == i->functions[j].name[k]) 98 | return i->functions[j].function; 99 | } 100 | printf("Imagine Error: Funtion: %s not found %u\n", name, i->function_count); 101 | return NULL; 102 | } 103 | 104 | ILib *imagine_library_load(char *path, IInterface *iinterface, char *interface_name) 105 | { 106 | IInterface *(*imagine_lib_main)(IInterface *exe_interface); 107 | char *(*imagine_lib_name)(void); 108 | void *dll; 109 | ILib *lib; 110 | char *name; 111 | unsigned int i; 112 | #ifdef UNICODE 113 | short u_path[1025]; 114 | for(i = 0; i < 1024 && path[i] !=0 ; i++) 115 | u_path[i] = (char)path[i]; 116 | u_path[i] = 0; 117 | dll = i_internal_lib_load(u_path); 118 | #else 119 | dll = i_internal_lib_load(path); 120 | #endif 121 | if(dll == NULL) 122 | { 123 | #ifdef _WIN32 124 | printf("Imagine ERROR: library %s not found. Windows error code: %u\n", path, GetLastError()); 125 | #else 126 | printf("Imagine ERROR: library %s not found.\n", path); 127 | #endif 128 | return NULL; 129 | } 130 | if(interface_name != NULL) 131 | { 132 | imagine_lib_name = (char *(*)(void))i_internal_lib_get_address(dll, "imagine_lib_name"); 133 | 134 | if(imagine_lib_name == NULL) 135 | { 136 | i_internal_lib_unload(dll); 137 | printf("Imagine ERROR: imagine_lib_name not found in %s.\n", path); 138 | return NULL; 139 | } 140 | name = imagine_lib_name(); 141 | for(i = 0; interface_name[i] != 0 && interface_name[i] == name[i]; i++); 142 | 143 | if(interface_name[i] != name[i]) 144 | { 145 | printf("Imagine ERROR: Dll %s is of type %s not %s.\n", path, name, interface_name); 146 | i_internal_lib_unload(dll); 147 | return NULL; 148 | } 149 | } 150 | #ifdef WIN32 151 | imagine_lib_main = (char *(*)(void))GetProcAddress(dll, "imagine_lib_main"); 152 | #else 153 | imagine_lib_main = dlsym(dll, "imagine_lib_main"); 154 | #endif 155 | if(imagine_lib_main == NULL) 156 | { 157 | printf("Imagine ERROR: imagine_lib_main not found in %s.\n", path); 158 | i_internal_lib_unload(dll); 159 | return NULL; 160 | } 161 | 162 | lib = malloc(sizeof *lib); 163 | 164 | lib->dll = dll; 165 | lib->dll_interface = imagine_lib_main(iinterface); 166 | lib->exe_interface = iinterface; 167 | return lib; 168 | } 169 | 170 | typedef unsigned char boolean; 171 | 172 | void imagine_library_unload(ILib *lib, boolean interface_delete) 173 | { 174 | imagine_library_interface_destroy(lib->dll_interface); 175 | if(interface_delete) 176 | imagine_library_interface_destroy(lib->exe_interface); 177 | i_internal_lib_unload(lib->dll); 178 | free(lib); 179 | } 180 | 181 | -------------------------------------------------------------------------------- /hxa_utils.h: -------------------------------------------------------------------------------- 1 | #include "hxa.h" 2 | 3 | 4 | 5 | /* ------- disk stoarge ------------ 6 | Functions for saving and loading HxA files to and from disk. */ 7 | 8 | extern HXAFile *hxa_load(char *file_name, int silent); /* Load a Hxa file in to memory.*/ 9 | extern int hxa_save(char *file_name, HXAFile *data); /* Save a HxA structure to disk. */ 10 | 11 | extern void hxa_util_primitive_cube(HXAFile *file, double x, double y, double z); 12 | 13 | extern void hxa_util_free_node_content(HXANode *node); /* frees the content of a node but does not free the node pointer itself */ 14 | extern void hxa_util_free_file(HXAFile *file); /* Frees an entire HxA structure. */ 15 | 16 | /* ------- validation ------------ 17 | Validates that the content of HxA structure. */ 18 | extern int hxa_util_validate(HXAFile *file, int silent); /* Validates the HxA file to contain valid data. */ 19 | extern int hxa_util_validate_pow(HXAFile *file, int silent); /* Validate that all images are of Power of two resolution. */ 20 | 21 | 22 | /* ------- validation ------------ 23 | Validates that the content of HxA structure. */ 24 | extern void hxa_print(HXAFile *file, int data); /* Prints the content of a Hxa structure to stdout in a human readable form. If data is set to TRUE, Array content will be printed, otherwise not.*/ 25 | extern void hxa_print_meta_find(HXAFile *file, char *key); 26 | 27 | extern void hxa_util_meta_add(HXAMeta **meta_data, hxa_uint32 *meta_data_count, char *name, HXAMetaDataType type, void *data, unsigned int length, int copy); /* Adds a Meta data entry to a node. If copy is set to TRUE the function will allocate the memory needed to store the data and copy the data to it. If copy is set to FALSE the user provided pointer will be used by the structure.*/ 28 | extern void *hxa_util_meta_get(HXAMeta *meta_data, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type, unsigned int *length, int recursive); /* Searches for a Meta tag with a specific type and name and returns a pointer to it. It will also write the*/ 29 | extern unsigned int hxa_util_meta_get_next(HXAMeta *meta_data, hxa_uint32 start, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type); 30 | 31 | #define hxa_ref(ref, a) (ref[a] >= 0 ? ref[a] : (-ref[a] - 1)) /* A macro that converts all ref values to positive references. */ 32 | extern int hxa_corner_get_next(int *ref, unsigned int corner); /* Returns the position of the next reference value in a polygon from one corner. */ 33 | extern int hxa_corner_get_previous(int *ref, unsigned int corner); /* Returns the position of the next reference value in a polygon from one corner. */ 34 | extern int hxa_edge_get_next(int *ref, unsigned int *neighbour, unsigned int edge); 35 | extern int hxa_edge_get_previous(int *ref, unsigned int *neighbour, unsigned int edge); 36 | extern unsigned int *hxa_neighbour_node(HXANode *node); /* Generates edge adjacensy information for a geometry mesh. */ 37 | extern void hxa_neighbour_file(HXAFile *file); /* Generates neighbour data for all geometry nodes in a HxA structure. */ 38 | 39 | extern HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b); /* Merges two HxA structures in to one. */ 40 | 41 | 42 | extern void hxa_util_convert_layer_float_to_double(HXALayer *layer, unsigned int count); /* Converts a layer from single precission float to double precission floats. */ 43 | extern void hxa_util_convert_layer_double_to_float(HXALayer *layer, unsigned int count); /* Converts a layer from double precission float to single precission floats. */ 44 | extern void hxa_util_convert_stack_float_to_double(HXALayerStack *stack, unsigned int count); /* Converts a layer stack from single precission float to double precission floats. */ 45 | extern void hxa_util_convert_stack_double_to_float(HXALayerStack *stack, unsigned int count); /* Converts a layer stack from double precission float to single precission floats. */ 46 | extern void hxa_util_convert_node_float_to_double(HXANode *node); /* Converts all layer in a node from single precission float to double precission floats. */ 47 | extern void hxa_util_convert_node_double_to_float(HXANode *node); /* Converts all layer in a node from double precission float to single precission floats. */ 48 | 49 | extern void hxa_util_node_vertex_purge(HXANode *node); /* removes any unused vertices from a node */ 50 | extern void hxa_util_vertex_purge(HXAFile *file); /* removes any unused vertices from a structure */ 51 | 52 | extern void hxa_util_normal_corner(HXANode *node); 53 | 54 | extern void hxa_util_triangulate_node(HXANode *node, unsigned int max_sides); /* Splits all n-gons with more sides then max_sides in to triangles. */ 55 | 56 | extern void hxa_corner_to_vertex(HXANode *node); /**/ 57 | 58 | extern void hxa_close_node(HXANode *node); /* Closes all holes in a polygon mesh */ 59 | extern void hxa_close_file(HXAFile *file); /* Closes all holes in all polygon meshes */ 60 | 61 | 62 | 63 | extern HXAFile *hxa_util_true_type_load(char *file_name); /* loads a Truetype font and converts in in to polygon nodes. */ 64 | 65 | extern HXAFile *hxa_util_fbx_load(char *file_name, HXAFile *hxa_file); 66 | 67 | typedef enum{ 68 | HXA_UAET_INT8, 69 | HXA_UAET_UINT8, 70 | HXA_UAET_INT16, 71 | HXA_UAET_UINT16, 72 | HXA_UAET_INT32, 73 | HXA_UAET_UINT32, 74 | HXA_UAET_HALF16, 75 | HXA_UAET_FLOAT32, 76 | HXA_UAET_DOUBLE64, 77 | HXA_UAET_COUNT 78 | }HxAUtilArrayExportTypes; 79 | 80 | unsigned char *hxa_type_vertex_convert(HXANode *node, unsigned char *buffer, unsigned int param_count, char **param_names, HxAUtilArrayExportTypes *param_types, unsigned int *param_dimentions); 81 | unsigned char *hxa_type_reference_convert(HXANode *node, unsigned char *buffer, unsigned int param_count, char **param_names, HxAUtilArrayExportTypes *param_types, unsigned int *param_dimentions); 82 | -------------------------------------------------------------------------------- /hxa_util_validate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | int hxa_util_validate_meta(HXAMeta *meta, unsigned int node, unsigned int count, int silent) 11 | { 12 | unsigned int i; 13 | if(meta->type == HXA_MDT_NODE) 14 | { 15 | for(i = 0; meta->array_length; i++) 16 | { 17 | if(meta->value.node_value[i] >= count) 18 | { 19 | if(!silent) 20 | printf("HxA Verify Error: Node %u has meta data %s that is referencing a non existant node (%u out of %u)\n", node, meta->name, meta->value.node_value[i], count); 21 | return FALSE; 22 | } 23 | } 24 | } 25 | if(meta->type == HXA_MDT_META) 26 | for(i = 0; meta->array_length; i++) 27 | if(!hxa_util_validate_meta(&((HXAMeta *)meta->value.node_value)[i], node, count, silent)) 28 | return FALSE; 29 | return TRUE; 30 | } 31 | 32 | int hxa_util_validate(HXAFile *file, int silent) 33 | { 34 | char *layer_type_names[4] = {"HXA_LDT_UINT8", "HXA_LDT_INT32", "HXA_LDT_FLOAT", "HXA_LDT_DOUBLE"}, *test; 35 | unsigned int i, j, poly_count, reference; 36 | int *ref; 37 | HXANode *node; 38 | node = file->node_array; 39 | for(i = 0; i < file->node_count; i++) 40 | { 41 | for(i = 0; i < node->meta_data_count; i++) 42 | if(!hxa_util_validate_meta(&node->meta_data[i], i, file->node_count, silent)) 43 | return FALSE; 44 | switch(node->type) 45 | { 46 | case HXA_NT_META_ONLY : 47 | break; 48 | case HXA_NT_GEOMETRY : 49 | if(node->content.geometry.vertex_stack.layer_count == 0) 50 | { 51 | if(!silent) 52 | printf("HxA Verify Error: Node %u has no vertex layer\n", i); 53 | return FALSE; 54 | } 55 | if(node->content.geometry.vertex_stack.layers[0].components != 3) 56 | { 57 | if(!silent) 58 | printf("HxA Verify Error: Node %u vertex layer vertex layer has %u compinents. Must be HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS (%u).\n", i, node->content.geometry.vertex_stack.layers[0].components, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS); 59 | return FALSE; 60 | } 61 | if(node->content.geometry.vertex_stack.layers[0].type != HXA_LDT_FLOAT && 62 | node->content.geometry.vertex_stack.layers[0].type != HXA_LDT_DOUBLE) 63 | { 64 | if(!silent) 65 | printf("HxA Verify Error: Node %u first vertex layer is %s, must be HXA_LDT_FLOAT or HXA_LDT_DOUBLE\n", i, layer_type_names[node->content.geometry.vertex_stack.layers[0].type]); 66 | return FALSE; 67 | } 68 | test = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME; 69 | for(j = 0; test[j] != 0 && node->content.geometry.vertex_stack.layers[0].name[j] != test[j]; j++); 70 | if(node->content.geometry.vertex_stack.layers[0].name[j] != test[j]) 71 | { 72 | if(!silent) 73 | printf("HxA Verify Error: Node %u vertex layer is named %s. Must be HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME \"%s\".\n", i, node->content.geometry.vertex_stack.layers[0].name, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME); 74 | return FALSE; 75 | } 76 | if(node->content.geometry.corner_stack.layer_count != 0) 77 | { 78 | if(node->content.geometry.corner_stack.layers[0].components != 1) 79 | { 80 | if(!silent) 81 | printf("HxA Verify Error: Node %u reference layer has %u compinents. Must be 1.\n", i, node->content.geometry.corner_stack.layers[0].components); 82 | return FALSE; 83 | } 84 | if(node->content.geometry.corner_stack.layers[0].type != HXA_LDT_INT32) 85 | { 86 | if(!silent) 87 | printf("HxA Verify Error: Node %u reference layer is of type %s, must be HXA_LDT_INT32\n", i, layer_type_names[node->content.geometry.corner_stack.layers[0].type]); 88 | return FALSE; 89 | } 90 | test = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME; 91 | for(j = 0; test[j] != 0 && node->content.geometry.corner_stack.layers[0].name[j] != test[j]; j++); 92 | if(node->content.geometry.corner_stack.layers[0].name[j] != test[j]) 93 | { 94 | if(!silent) 95 | printf("HxA Verify Error: Node %u reference layer is named %s. Must be HXA_CONVENTION_HARD_BASE_EDGE_CORNER_LAYER_NAME \"%s\".\n", i, node->content.geometry.corner_stack.layers[0].name, HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME); 96 | return FALSE; 97 | } 98 | ref = node->content.geometry.corner_stack.layers[0].data.int32_data; 99 | for(j = poly_count = 0; j < node->content.geometry.edge_corner_count; j++) 100 | { 101 | if(ref[j] < 0) 102 | { 103 | reference = -ref[j] - 1; 104 | poly_count++; 105 | }else 106 | reference = ref[j]; 107 | if(reference >= node->content.geometry.vertex_count) 108 | { 109 | if(!silent) 110 | printf("HxA Verify Error: Node %u has a reference value referencing a non existing vertex (%u).\n", i, reference); 111 | return FALSE; 112 | } 113 | } 114 | if(node->content.geometry.face_count != poly_count) 115 | { 116 | if(!silent) 117 | printf("HxA Verify Error: Node %u claims to have %u faces but the reference data has %u faces.\n", i, node->content.geometry.face_count , poly_count); 118 | return FALSE; 119 | } 120 | } 121 | break; 122 | case HXA_NT_IMAGE : 123 | break; 124 | } 125 | node++; 126 | } 127 | return TRUE; 128 | } 129 | 130 | 131 | 132 | int hxa_util_validate_pow(HXAFile *file, int silent) 133 | { 134 | unsigned int i, j, k, dim, success = TRUE; 135 | for(i = 0; i < file->node_count; i++) 136 | { 137 | if(file->node_array[i].type == HXA_NT_IMAGE) 138 | { 139 | dim = file->node_array[i].content.image.type; 140 | if(dim == HXA_IT_CUBE_IMAGE) 141 | dim = 2; 142 | for(j = 0; j < dim; j++) 143 | { 144 | for(k = 1; k < file->node_array[i].content.image.resolution[j]; k *= 2); 145 | if(k > file->node_array[i].content.image.resolution[j]) 146 | { 147 | if(!silent) 148 | printf("HxA Verify Error: Node has non power of two resolution (%u)\n", file->node_array[i].content.image.resolution[j]); 149 | success = FALSE; 150 | } 151 | } 152 | } 153 | } 154 | return success; 155 | } -------------------------------------------------------------------------------- /hxa_upi.h: -------------------------------------------------------------------------------- 1 | #include "hxa.h" 2 | 3 | /* HxA Universal Pluging Interface (UPI) 4 | ------------------------------------- 5 | 6 | This is the HxA universal plugin interface. The idea is to use the simple HxA data structure to create a plugin interface for asset 7 | manipulation that is so simple that it can be implemented in any DCC application. It lets you wrap code that reads and writes HxA 8 | structures in to dynamicly loadable libraries. You can specify what parameters the code takes, so that an applictaion can build an 9 | interface that acceeses the functionality. This makes it easy to build a node, stack or filter based tool that uses any HxA 10 | processing algorithm by dynamicly loading them. It also means that a HxA plugin wraped as a UPI can be loaded in any applictaion that 11 | suppiorts HxA plugins. One Plugin AIP, multiple applications? Hell Yeah!! 12 | 13 | */ 14 | 15 | /* qualifyer needed to expose a function to a library loader*/ 16 | #ifdef _WIN32 17 | #define HxALibExport _declspec (dllexport) 18 | #else 19 | #define IMAGINE_ATOMIC_EMULATION 20 | #define ILibExport 21 | #endif 22 | 23 | /* Parameter types 24 | --------------------*/ 25 | 26 | typedef enum{ 27 | HXA_UPI_IPT_BOOLEAN, /* checkbox */ 28 | HXA_UPI_IPT_SIGNED_INTEGER, /* int */ 29 | HXA_UPI_IPT_UNSIGNED_INTEGER, /* insigned integer */ 30 | HXA_UPI_IPT_DOUBLE_BOUND, /* double 0 - 1.0 (slider)*/ 31 | HXA_UPI_IPT_DOUBLE_UNBOUND, /* double */ 32 | HXA_UPI_IPT_POS_2D, /* 2D position */ 33 | HXA_UPI_IPT_POS_3D, /* 3D position */ 34 | HXA_UPI_IPT_VECTOR_2D, /* 2D vector */ 35 | HXA_UPI_IPT_VECTOR_3D, /* 3D vector */ 36 | HXA_UPI_IPT_MATRIX, /* 4x4 colum major transform Matrix*/ 37 | HXA_UPI_IPT_COLOR, /* RGB value */ 38 | HXA_UPI_IPT_TEXT, /* text input. Can be NULL */ 39 | HXA_UPI_IPT_PATH_READ, /* File path for reading. Can be NULL */ 40 | HXA_UPI_IPT_PATH_WRITE, /* File path for writing. Can be NULL */ 41 | HXA_UPI_IPT_SELECT, /* multi option select */ 42 | HXA_UPI_IPT_HXA_READ, /* A HXA structure to be read only. Can be NULL */ 43 | HXA_UPI_IPT_HXA_CONSUME, /* A HXA structure, that will be read and freed/returned by the plugin. Can be NULL */ 44 | HXA_UPI_IPT_COUNT, 45 | }HXAUPIInterfaceParamType; 46 | 47 | 48 | /* Parameters descriptions 49 | ---------------------------*/ 50 | 51 | typedef struct{ 52 | HXAUPIInterfaceParamType type; // what type of node is this? Stored in the file as a uint8. 53 | char *name; // What is the parameter named. keep it short so it fits in a UI. 54 | char *description; // Longer desriptive text. Used for things like tooltips and generated documentation. 55 | /* the union below describes either the value of a parameter provided by the user at runtime, or the default value provided by the plugin at initialization. */ 56 | union{ 57 | int boolean; // checkbox 58 | int signed_integer; // signed integer 59 | unsigned int unsigned_integer; // unsigned integer 60 | double double_bound; // double value raning from 0 - 1. Can be shown as a slider. may be expresed as % in the UI. 61 | double double_value; // double value with infinit range. Can not be a NaN! 62 | double point_2d[2]; // 2D position. can be used for positions on a image. 63 | double point_3d[3]; // 3D position. Can be a 3D mainipulator. 64 | double vector_2d[2]; // 2D vector. if placed in a 2D UI, and following a HXA_IPT_POS_2D, start the vector at the previous position. 65 | double vector_3d[3]; // 3D vector. if placed in a 3D UI, and following a HXA_IPT_POS_3D or HXA_IPT_MATRIX, start the vector at the previous position. 66 | double matrix[16]; // 3D transform. includes Translation, Rotation and Scale. 67 | double color[3]; // RGB value. UIs are expected to have some sort of color picker UI. 68 | char *text; // Null is legal 69 | char *path_read; // Null is legal 70 | char *path_write; // Null is legal 71 | struct{ 72 | char **option_names; // an array of option names. 73 | unsigned int option_count; // the number of options available. Must be at least 1. 74 | unsigned int selected; // currently selected. Must be no more then one less then option_count. 75 | }select; 76 | HXAFile *hxa; // A pointer to a HxA structure. This structure is write protected and should not be modified or returned !! 77 | }content; 78 | }HXAUPIInterfaceParam; 79 | 80 | /* Plugin API 81 | ---------------*/ 82 | 83 | /* This is the initialization function that a HxA UPI plugin needs to implement. An applictaion that wants 84 | to support HxA plugins will look for dunamicly loaded libraries that have this function implemented. 85 | The functions main first parameter is a function pointer to a function used by the plugin to register 86 | all things needed to describe a plugins interface and execution. Se exampel plugin below.*/ 87 | 88 | typedef struct{ 89 | HXAUPIInterfaceParam *params; /* parameters used by the plugin. */ 90 | unsigned int param_count; /* numer of params taken by the plugin. */ 91 | const char *name; /* name of the plugin. */ 92 | const char *descrtiption; /* text string describing the functionality of the plugin. */ 93 | int has_output; /* does the plugin return a HxAFile Struct pointer. */ 94 | void *(*instance_create_func)(HXAUPIInterfaceParam *params, void *user); /* creates an instance of the plugin. May be NULL. */ 95 | void (*instance_destroy_func)(HXAUPIInterfaceParam *params, void *instance, void *user); /* destroys an instance of the plugin. May be NULL if instance_create_func is also NULL. */ 96 | int (*instance_update_func)(HXAUPIInterfaceParam *params, void *instance, void *user); /*tests if the instance needs updating. May be NULL. */ 97 | HXAFile *(*execute_func)(HXAUPIInterfaceParam *params, void *instance, void *user); /**/ 98 | void *user; /* user pointer that will be given to all above function pointers when called. */ 99 | void *library; /* internal handle for the loaded library, so that it can be unloaded. */ 100 | }HxAUPIPlugin; 101 | 102 | extern void hxa_upi_plugin_library_initialize(void (*register_func)(HxAUPIPlugin *plugin)); 103 | 104 | 105 | /* Reference host API 106 | -----------------------*/ 107 | 108 | extern HxAUPIPlugin *hxa_upi_host_load_library(char *path, unsigned int *plugin_count); /* Loads a single library file. */ 109 | extern HxAUPIPlugin *hxa_upi_host_load_directory(char *path, unsigned int *plugin_count); /* loads all libraries in a specific path (like a plugin directory).*/ 110 | extern void hxa_upi_host_unload_library(char *path, HxAUPIPlugin *plugins, unsigned int plugin_count); /* unloads all libraries and frees memory */ 111 | 112 | -------------------------------------------------------------------------------- /hxa_util_command_line.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_utils.h" 6 | 7 | #define FALSE 0 8 | #define TRUE !FALSE 9 | 10 | int hxa_convert_param_to_int(char *string, int *output) 11 | { 12 | unsigned int i = 0; 13 | *output = 0; 14 | if(string[i] == '-') 15 | i++; 16 | 17 | if(string[i] < '0' && string[i] > '9') 18 | return 0; 19 | *output += (unsigned int)string[i++] - (unsigned int)'0'; 20 | while(string[i] < '0' && string[i] > '9') 21 | { 22 | *output *= 10; 23 | *output += (unsigned int)string[i++] - (unsigned int)'0'; 24 | } 25 | if(string[0] == '-') 26 | *output = -*output; 27 | return i; 28 | } 29 | 30 | int hxa_type_test(char *path, char *type) 31 | { 32 | unsigned int i, j; 33 | for(i = 0; path[i] != 0; i++) 34 | { 35 | if(path[i] == '.') 36 | { 37 | i++; 38 | for(j = 0; type[j] != 0 && path[i + j] != 0 && (path[i + j] == type[j] || path[i + j] + 32 == type[j]); j++); 39 | if(type[j] == 0) 40 | return TRUE; 41 | } 42 | } 43 | return FALSE; 44 | } 45 | 46 | extern int hxa_load_png(HXAFile *file, char *file_name); 47 | extern void hxa_type_convert_gen(); 48 | 49 | int main(int argc, char **argv) 50 | { 51 | HXAFile *file = NULL, *file2; 52 | unsigned int i, j, silent, save, int_param; 53 | 54 | // hxa_type_convert_gen(); 55 | if(argc < 2) 56 | { 57 | printf("HxA utility. Written by Eskil Steenberg www.quelsolaar.com. MIT License\n"); 58 | printf("Usage: %s \n", argv[0]); 59 | printf("argument operations are executed in order.\n"); 60 | printf("Argument list:\n"); 61 | printf(" - \"validate\" validates the file to make sure it is correct. Non valid files may cause the tools to fail.\n"); 62 | printf(" - \"powvalid\" validates that all images in a file have power of two resolution.\n"); 63 | printf(" - \"neighbour\" compute a neighbour layer storing adjacency.\n"); 64 | printf(" - \"save\" write out the file.\n"); 65 | printf(" - \"d2f\" converts all double precission layers to float layers.\n"); 66 | printf(" - \"f2d\" converts all float layers to double precission layers.\n"); 67 | printf(" - \"triangulate\" Converts all polygons with more sides then in to triangles.\n"); 68 | printf(" - \"vertexpurge\" Removes any unreferenced vertex from the file.\n"); 69 | printf(" - \"close\" Closes any holes in meshes.\n"); 70 | printf(" - \"print\" prints the structure of the file.\n"); 71 | printf(" - \"printall\" prints the structure and data the file.\n"); 72 | printf(" - \"printmeta\" prints the value of meta entries of a specific name.\n"); 73 | return TRUE; 74 | } 75 | for(i = 3; i < argc && strcmp(argv[i], "silent") != 0; i++); 76 | silent = i != argc; 77 | 78 | 79 | if(hxa_type_test(argv[1], "fbx")) 80 | { 81 | if(!silent) 82 | printf("Loading Autodesk FBX file: %s\n", argv[1]); 83 | file = hxa_util_fbx_load(argv[1], NULL); 84 | if(!silent && file == NULL) 85 | printf("HxA Error: FBX load failed.\n"); 86 | }else if(hxa_type_test(argv[1], "ttf") || hxa_type_test(argv[1], "tte") || hxa_type_test(argv[1], "dfont") || hxa_type_test(argv[1], "otf") || hxa_type_test(argv[1], "otc") || hxa_type_test(argv[1], "ttf") || hxa_type_test(argv[1], "ttc")) 87 | { 88 | if(!silent) 89 | printf("Loading TrueType font file: %s\n", argv[1]); 90 | file = hxa_util_true_type_load(argv[1]); 91 | if(!silent && file == NULL) 92 | printf("HxA Error: TrueType load failed.\n"); 93 | }else if(hxa_type_test(argv[1], "png")) 94 | { 95 | if(!silent) 96 | printf("Loading PNG image file: %s\n", argv[1]); 97 | file = hxa_util_true_type_load(argv[1]); 98 | if(!silent && file == NULL) 99 | printf("HxA Error: PNG image load failed.\n"); 100 | } 101 | if(file == NULL) 102 | { 103 | if(!silent) 104 | printf("Loading HxA file: %s\n", argv[1]); 105 | file = hxa_load(argv[1], silent); 106 | if(!silent && file == NULL) 107 | { 108 | printf("HxA Error: Loading file failed. Exiting...\n"); 109 | return 0; 110 | } 111 | } 112 | 113 | save = TRUE; 114 | for(i = 2; i < argc; i++) 115 | { 116 | if(strcmp(argv[i], "save") == 0) 117 | { 118 | if(++i < argc) 119 | { 120 | if(!silent) 121 | printf("Saving HxA file: %s\n", argv[i]); 122 | if(!hxa_save(argv[i], file) && !silent) 123 | { 124 | printf("Saving file failed. Exiting...\n"); 125 | return FALSE; 126 | } 127 | }else 128 | { 129 | printf("HxA Error: \"save\" is missing a filename parameter. Exiting...\n"); 130 | return FALSE; 131 | } 132 | }else if(strcmp(argv[i], "validate") == 0) 133 | { 134 | if(!hxa_util_validate(file, silent)) 135 | return FALSE; 136 | }else if(strcmp(argv[i], "powvalid") == 0) 137 | { 138 | if(!hxa_util_validate_pow(file, silent)) 139 | return FALSE; 140 | }else if(strcmp(argv[i], "neighbour") == 0) 141 | { 142 | hxa_neighbour_file(file); 143 | }else if(strcmp(argv[i], "f2d") == 0) 144 | { 145 | for(j = 0; j < file->node_count; j++) 146 | hxa_util_convert_node_float_to_double(&file->node_array[j]); 147 | }else if(strcmp(argv[i], "d2f") == 0) 148 | { 149 | for(j = 0; j < file->node_count; j++) 150 | hxa_util_convert_node_double_to_float(&file->node_array[j]); 151 | }else if(strcmp(argv[i], "triangulate") == 0) 152 | { 153 | if(hxa_convert_param_to_int(argv[++i], &int_param) && int_param > 2) 154 | { 155 | for(j = 0; j < file->node_count; j++) 156 | hxa_util_triangulate_node(&file->node_array[j], int_param); 157 | }else 158 | { 159 | printf("HxA Error: the command param \"triangulate\" must be a folowed by a integer param set to 3 or larger"); 160 | return FALSE; 161 | } 162 | }else if(strcmp(argv[i], "vertexpurge") == 0) 163 | { 164 | hxa_util_vertex_purge(file); 165 | }else if(strcmp(argv[i], "close") == 0) 166 | { 167 | hxa_close_file(file); 168 | }else if(strcmp(argv[i], "print") == 0) 169 | { 170 | hxa_print(file, FALSE); 171 | }else if(strcmp(argv[i], "printall") == 0) 172 | { 173 | hxa_print(file, TRUE); 174 | }else if(strcmp(argv[i], "printmeta") == 0) 175 | { 176 | if(++i < argc) 177 | hxa_print_meta_find(file, argv[i]); 178 | else 179 | { 180 | printf("HxA Error: \"printmeta\" is missing a key parameter. Exiting...\n"); 181 | return FALSE; 182 | } 183 | }else if(strcmp(argv[i], "merge") == 0) 184 | { 185 | file2 = hxa_load(argv[++i], silent); 186 | if(file2 != NULL) 187 | hxa_util_merge(file, file2); 188 | else 189 | return FALSE; 190 | }else 191 | { 192 | if(i == 2) 193 | save = TRUE; 194 | else 195 | { 196 | printf("HxA Error: Parameter \"%s\" is invalid. Exiting...\n", argv[i]); 197 | return FALSE; 198 | } 199 | } 200 | } 201 | return TRUE; 202 | } 203 | -------------------------------------------------------------------------------- /hxa_util_normals.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #pragma warning(disable:4996) 3 | #pragma warning(disable:4703) 4 | #pragma warning(disable:4996) 5 | #pragma warning(disable:4664) 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "hxa.h" 11 | #include "hxa_utils.h" 12 | 13 | #define FALSE 0 14 | #define TRUE !FALSE 15 | 16 | 17 | /* use include and defines to creat float and double versions of the normal functions. */ 18 | #define NORMAL_FACE 19 | #define HXATYPE_DATA float_data 20 | #define HXATYPE float 21 | #define hxa_util_normal_face_macro hxa_util_normal_facef 22 | #include "hxa_util_normals.h" 23 | #define HXATYPE_DATA double_data 24 | #define HXATYPE double 25 | #define hxa_util_normal_face_macro hxa_util_normal_faced 26 | #include "hxa_util_normals.h" 27 | #undef NORMAL_FACE 28 | #define NORMAL_CORNER 29 | 30 | #define HXATYPE_DATA float_data 31 | #define HXATYPE float 32 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerf 33 | #include "hxa_util_normals.h" 34 | #define HXATYPE_DATA double_data 35 | #define HXATYPE double 36 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerd 37 | #include "hxa_util_normals.h" 38 | #define HXATYPE_DATA float_data 39 | #define HXATYPE float 40 | #define HXA_CREASE_TYPE unsigned char 41 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerf_u8 42 | #include "hxa_util_normals.h" 43 | #define HXA_CREASE_TYPE int 44 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerf_i32 45 | #include "hxa_util_normals.h" 46 | #define HXA_CREASE_TYPE float 47 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerf_f 48 | #include "hxa_util_normals.h" 49 | #define HXA_CREASE_TYPE double 50 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerf_d 51 | #include "hxa_util_normals.h" 52 | #define HXATYPE_DATA double_data 53 | #define HXATYPE double 54 | #define HXA_CREASE_TYPE unsigned char 55 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerd_u8 56 | #include "hxa_util_normals.h" 57 | #define HXA_CREASE_TYPE int 58 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerd_i32 59 | #include "hxa_util_normals.h" 60 | #define HXA_CREASE_TYPE float 61 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerd_f 62 | #include "hxa_util_normals.h" 63 | #define HXA_CREASE_TYPE double 64 | #define hxa_util_normal_corner_macro hxa_util_normal_cornerd_d 65 | #include "hxa_util_normals.h" 66 | 67 | 68 | 69 | void hxa_util_normal_face(HXANode *node) 70 | { 71 | HXALayer *layer; 72 | node->content.geometry.face_stack.layer_count++; 73 | node->content.geometry.face_stack.layers = realloc(node->content.geometry.face_stack.layers, (sizeof *node->content.geometry.face_stack.layers) * node->content.geometry.face_stack.layer_count); 74 | layer = &node->content.geometry.face_stack.layers[node->content.geometry.face_stack.layer_count - 1]; 75 | layer->type = node->content.geometry.vertex_stack.layers[0].type; 76 | layer->components = 3; 77 | sprintf(layer->name, HXA_CONVENTION_SOFT_LAYER_NORMALS); 78 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 79 | layer->data.float_data = hxa_util_normal_facef(node); 80 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 81 | layer->data.double_data = hxa_util_normal_faced(node); 82 | } 83 | 84 | void hxa_util_normal_corner(HXANode *node) 85 | { 86 | char *crease_name = HXA_CONVENTION_SOFT_LAYER_CREASES; 87 | HXALayer *layer; 88 | unsigned int i, j, *neighbour, *face_ref; 89 | int *ref; 90 | void *face_data; 91 | node->content.geometry.corner_stack.layer_count++; 92 | node->content.geometry.corner_stack.layers = realloc(node->content.geometry.corner_stack.layers, (sizeof *node->content.geometry.corner_stack.layers) * node->content.geometry.corner_stack.layer_count); 93 | layer = &node->content.geometry.corner_stack.layers[node->content.geometry.corner_stack.layer_count - 1]; 94 | layer->type = node->content.geometry.vertex_stack.layers[0].type; 95 | layer->components = 3; 96 | sprintf(layer->name, HXA_CONVENTION_SOFT_LAYER_NORMALS); 97 | face_ref = malloc((sizeof *face_ref) * node->content.geometry.edge_corner_count); 98 | ref = node->content.geometry.corner_stack.layers[0].data.int32_data; 99 | for(i = j = 0; i < node->content.geometry.edge_corner_count; i++) 100 | { 101 | face_ref[i] = j; 102 | if(ref[i] < 0) 103 | j++; 104 | } 105 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 106 | face_data = hxa_util_normal_facef(node); 107 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 108 | face_data = hxa_util_normal_faced(node); 109 | neighbour = hxa_neighbour_node(node); 110 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 111 | if(neighbour[i] < node->content.geometry.edge_corner_count && neighbour[neighbour[i]] != i) 112 | i += 0; 113 | for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++) 114 | { 115 | for(j = 0; node->content.geometry.edge_stack.layers[i].name[j] == crease_name[j] && crease_name[j] != 0; j++); 116 | if(node->content.geometry.edge_stack.layers[i].name[j] == crease_name[j]) 117 | { 118 | switch(node->content.geometry.edge_stack.layers[i].type) 119 | { 120 | case HXA_LDT_UINT8 : 121 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 122 | layer->data.float_data = hxa_util_normal_cornerf_u8(node, neighbour, node->content.geometry.edge_stack.layers[i].data.uint8_data, (float *)face_data, face_ref); 123 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 124 | layer->data.double_data = hxa_util_normal_cornerd_u8(node, neighbour, node->content.geometry.edge_stack.layers[i].data.uint8_data, (double *)face_data, face_ref); 125 | break; 126 | case HXA_LDT_INT32 : 127 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 128 | layer->data.float_data = hxa_util_normal_cornerf_i32(node, neighbour, node->content.geometry.edge_stack.layers[i].data.int32_data, (float *)face_data, face_ref); 129 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 130 | layer->data.double_data = hxa_util_normal_cornerd_i32(node, neighbour, node->content.geometry.edge_stack.layers[i].data.int32_data, (double *)face_data, face_ref); 131 | break; 132 | case HXA_LDT_FLOAT : 133 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 134 | layer->data.float_data = hxa_util_normal_cornerf_f(node, neighbour, node->content.geometry.edge_stack.layers[i].data.float_data, (float *)face_data, face_ref); 135 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 136 | layer->data.double_data = hxa_util_normal_cornerd_f(node, neighbour, node->content.geometry.edge_stack.layers[i].data.float_data, (double *)face_data, face_ref); 137 | break; 138 | case HXA_LDT_DOUBLE : 139 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 140 | layer->data.float_data = hxa_util_normal_cornerf_d(node, neighbour, node->content.geometry.edge_stack.layers[i].data.double_data, (float *)face_data, face_ref); 141 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 142 | layer->data.double_data = hxa_util_normal_cornerd_d(node, neighbour, node->content.geometry.edge_stack.layers[i].data.double_data, (double *)face_data, face_ref); 143 | break; 144 | } 145 | free(face_ref); 146 | free(face_data); 147 | return; 148 | } 149 | } 150 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 151 | layer->data.float_data = hxa_util_normal_cornerf(node, neighbour, (float *)face_data, face_ref); 152 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 153 | layer->data.double_data = hxa_util_normal_cornerd(node, neighbour, (double *)face_data, face_ref); 154 | free(face_ref); 155 | free(face_data); 156 | } -------------------------------------------------------------------------------- /hxa_print.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | 6 | #define FALSE 0 7 | #define TRUE !FALSE 8 | 9 | extern void hxa_print_meta(HXAMeta *meta, unsigned int tab_count, unsigned int data); 10 | 11 | void hxa_print_meta_data(HXAMeta *meta, unsigned int length, unsigned int tab_count, unsigned int data) 12 | { 13 | unsigned int i; 14 | switch(meta->type) 15 | { 16 | case HXA_MDT_INT64 : 17 | for(i = 0; i < length; i++) 18 | printf(" %lli", meta->value.int64_value[i]); 19 | break; 20 | case HXA_MDT_DOUBLE : 21 | for(i = 0; i < length; i++) 22 | printf(" %f", meta->value.double_value[i]); 23 | break; 24 | case HXA_MDT_NODE : 25 | for(i = 0; i < length; i++) 26 | printf( "%i", meta->value.node_value[i]); 27 | break; 28 | case HXA_MDT_TEXT : 29 | printf(" %s", meta->value.text_value); 30 | break; 31 | case HXA_MDT_BINARY : 32 | for(i = 0; i < length; i++) 33 | printf(" %x", meta->value.bin_value[i]); 34 | break; 35 | case HXA_MDT_META : 36 | printf("\n"); 37 | for(i = 0; i < meta->array_length; i++) 38 | hxa_print_meta(&((HXAMeta *)meta->value.array_of_meta)[i], tab_count + 1, data); 39 | break; 40 | } 41 | } 42 | 43 | void hxa_print_meta_meta_find(HXAMeta *meta, char *key) 44 | { 45 | unsigned int i, j; 46 | if(strcmp(meta->name, key) == 0) 47 | hxa_print_meta_data(meta, meta->array_length, 0, TRUE); 48 | if(meta->type == HXA_MDT_META) 49 | for(i = 0; i < meta->array_length; i++) 50 | hxa_print_meta_meta_find(&((HXAMeta *)meta->value.array_of_meta)[i], key); 51 | } 52 | 53 | void hxa_print_meta_find(HXAFile *file, char *key) 54 | { 55 | unsigned int i, j; 56 | for(i = 0; i < file->node_count; i++) 57 | for(j = 0; j < file->node_array[i].meta_data_count; j++) 58 | hxa_print_meta_meta_find(&file->node_array[i].meta_data[j], key); 59 | } 60 | 61 | void hxa_print_meta(HXAMeta *meta, unsigned int tab_count, unsigned int data) 62 | { 63 | char *type_name[] = {"HXA_MDT_INT64", "HXA_MDT_DOUBLE", "HXA_MDT_NODE", "HXA_MDT_TEXT", "HXA_MDT_BINARY", "HXA_MDT_META"}; 64 | char tabs[16] = {'\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0}; 65 | unsigned int i, length; 66 | if(tab_count < 15) 67 | tabs[tab_count] = 0; 68 | if(meta->array_length == 1) 69 | printf("%s-Meta %s \"%s\" :", tabs, type_name[meta->type], meta->name); 70 | else 71 | printf("%s-Meta %s \"%s\"[%u] :", tabs, type_name[meta->type], meta->name, meta->array_length); 72 | length = meta->array_length; 73 | if(!data && length > 16) 74 | length = 16; 75 | hxa_print_meta_data(meta, length, tab_count, data); 76 | if(meta->type != HXA_MDT_META) 77 | { 78 | if(length < meta->array_length && meta->type != HXA_MDT_TEXT) 79 | printf(" ...\n"); 80 | else 81 | printf("\n"); 82 | } 83 | } 84 | 85 | void hxa_print_layer_stack(HXALayerStack *stack, char *name, int data, unsigned int count) 86 | { 87 | char *type_names[] = {"HXA_LDT_UINT8", "HXA_LDT_INT32", "HXA_LDT_FLOAT", "HXA_LDT_DOUBLE"}; 88 | unsigned int i, j, k; 89 | printf("\t-%s layer count: %u\n", name, stack->layer_count); 90 | for(i = 0; i < stack->layer_count; i++) 91 | { 92 | printf("\t\tLayer name: %s\n", stack->layers[i].name); 93 | printf("\t\tLayer components: %u\n", (unsigned int)stack->layers[i].components); 94 | printf("\t\tLayer type: %s\n", type_names[stack->layers[i].type]); 95 | if(data) 96 | { 97 | switch(stack->layers[i].type) 98 | { 99 | case HXA_LDT_UINT8 : 100 | for(j = 0; j < count; j++) 101 | { 102 | printf("\t\t\t"); 103 | for(k = 0; k < stack->layers[i].components; k++) 104 | printf("%u ", (unsigned int)stack->layers[i].data.uint8_data[j * stack->layers[i].components + k]); 105 | printf("\n"); 106 | } 107 | break; 108 | case HXA_LDT_INT32 : 109 | if(i == 0 && strcmp(stack->layers[i].name, "reference") == 0 && stack->layers[i].components == 1) 110 | { 111 | printf("\t\t\t"); 112 | for(j = 0; j < count; j++) 113 | { 114 | printf("%i ", stack->layers[i].data.int32_data[j]); 115 | if(stack->layers[i].data.int32_data[j] < 0) 116 | { 117 | printf("\n"); 118 | if(j + 1 < count) 119 | printf("\t\t\t"); 120 | } 121 | } 122 | }else 123 | { 124 | for(j = 0; j < count; j++) 125 | { 126 | printf("\t\t\t"); 127 | for(k = 0; k < stack->layers[i].components; k++) 128 | printf("%i ", stack->layers[i].data.int32_data[j * stack->layers[i].components + k]); 129 | printf("\n"); 130 | } 131 | } 132 | break; 133 | case HXA_LDT_FLOAT : 134 | for(j = 0; j < count; j++) 135 | { 136 | printf("\t\t\t"); 137 | for(k = 0; k < stack->layers[i].components; k++) 138 | printf("%f ", stack->layers[i].data.float_data[j * stack->layers[i].components + k]); 139 | printf("\n"); 140 | } 141 | break; 142 | case HXA_LDT_DOUBLE : 143 | for(j = 0; j < count; j++) 144 | { 145 | printf("\t\t\t"); 146 | for(k = 0; k < stack->layers[i].components; k++) 147 | printf("%f ", stack->layers[i].data.double_data[j * stack->layers[i].components + k]); 148 | printf("\n"); 149 | } 150 | break; 151 | } 152 | } 153 | } 154 | } 155 | 156 | void hxa_print(HXAFile *file, int data) 157 | { 158 | char *node_type_names[3] = {"HXA_NT_META_ONLY", "HXA_NT_GEOMETRY", "HXA_NT_IMAGE"}; 159 | unsigned int i, j; 160 | printf("File version: %u\n", file->version); 161 | printf("Node count: %u\n", file->node_count); 162 | for(i = 0; i < file->node_count; i++) 163 | { 164 | printf("-Node id: %u\n", i); 165 | printf("\t-Node type: %s\n", node_type_names[file->node_array[i].type]); 166 | printf("\t-Node meta count: %u\n", file->node_array[i].meta_data_count); 167 | for(j = 0; j < file->node_array[i].meta_data_count; j++) 168 | hxa_print_meta(&file->node_array[i].meta_data[j], 2, data); 169 | switch(file->node_array[i].type) 170 | { 171 | case HXA_NT_GEOMETRY : 172 | printf("\t-Geometry vertex count: %u\n", file->node_array[i].content.geometry.vertex_count); 173 | hxa_print_layer_stack(&file->node_array[i].content.geometry.vertex_stack, "Vertex", data, file->node_array[i].content.geometry.vertex_count); 174 | printf("\t-Geometry edge count: %u\n", file->node_array[i].content.geometry.edge_corner_count); 175 | hxa_print_layer_stack(&file->node_array[i].content.geometry.corner_stack, "Corner", data, file->node_array[i].content.geometry.edge_corner_count); 176 | hxa_print_layer_stack(&file->node_array[i].content.geometry.edge_stack, "Edge", data, file->node_array[i].content.geometry.edge_corner_count); 177 | printf("\t-Geometry face count: %u\n", file->node_array[i].content.geometry.face_count); 178 | hxa_print_layer_stack(&file->node_array[i].content.geometry.face_stack, "Face", data, file->node_array[i].content.geometry.face_count); 179 | break; 180 | case HXA_NT_IMAGE : 181 | switch(file->node_array[i].content.image.type) 182 | { 183 | case HXA_IT_CUBE_IMAGE : 184 | printf("\t-Pixel type: HXA_IT_CUBE_IMAGE\n"); 185 | printf("\t-Pixel resolution: %u x %u x 6\n", file->node_array[i].content.image.resolution[0], file->node_array[i].content.image.resolution[1]); 186 | break; 187 | case HXA_IT_1D_IMAGE : 188 | printf("\t-Pixel type: HXA_IT_1D_IMAGE\n"); 189 | printf("\t-Pixel resolution: %u\n", file->node_array[i].content.image.resolution[0]); 190 | break; 191 | case HXA_IT_2D_IMAGE : 192 | printf("\t-Pixel type: HXA_IT_2D_IMAGE\n"); 193 | printf("\t-Pixel resolution: %u x %u\n", file->node_array[i].content.image.resolution[0], file->node_array[i].content.image.resolution[1]); 194 | break; 195 | case HXA_IT_3D_IMAGE : 196 | printf("\t-Pixel type: HXA_IT_3D_IMAGE\n"); 197 | printf("\t-Pixel resolution: %u x %u x %u\n", file->node_array[i].content.image.resolution[0], file->node_array[i].content.image.resolution[1], file->node_array[i].content.image.resolution[2]); 198 | break; 199 | } 200 | break; 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /hxa_util_inflate.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FALSE 0 4 | #define TRUE !FALSE 5 | 6 | typedef struct{ 7 | unsigned char *stream; 8 | unsigned char *end; 9 | unsigned bit; 10 | }HxAInflateBitStream; 11 | 12 | 13 | unsigned int hxa_inflate_read_bits(HxAInflateBitStream *stream, unsigned int bits) 14 | { 15 | unsigned int output, progress, read; 16 | output = *stream->stream >> stream->bit; 17 | memcpy(&read, stream->stream, 4); 18 | output = read >> stream->bit; 19 | output &= (1 << bits) - 1; 20 | stream->stream += (stream->bit + bits) / 8; 21 | stream->bit = (stream->bit + bits) & 7; 22 | return output; 23 | } 24 | 25 | 26 | int hxa_inflate_uncompressed(HxAInflateBitStream *stream, unsigned char *output, size_t *output_length) 27 | { 28 | unsigned int length; 29 | stream->bit = 0; 30 | stream->stream++; 31 | if(stream->stream + 4 > stream->end) 32 | { 33 | printf("HxA Error: Deflate error. Block header of uncompressed block is out of bounds.\n"); 34 | return FALSE; 35 | } 36 | length = 256 * stream->stream[1] + stream->stream[0]; 37 | if(length != ~(256 * (unsigned int)stream->stream[3] + (unsigned int)stream->stream[2])) 38 | { 39 | printf("HxA Error: Deflate error. Uncompressed block has non matching complement.\n"); 40 | return FALSE; 41 | } 42 | stream->stream += 4; 43 | if(stream->stream + length > stream->end) 44 | { 45 | printf("HxA Error: Deflate error. Uncompressed block has length that is out of bounds.\n"); 46 | return FALSE; 47 | } 48 | memcpy(&output[*output_length], stream->stream, length); 49 | stream->stream += length; 50 | *output_length += length; 51 | return TRUE; 52 | } 53 | 54 | unsigned int hxa_inflate_length_bits[30] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 6}; 55 | unsigned int hxa_inflate_length_base[30] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 323}; 56 | unsigned int hxa_inflate_distance_bits[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; 57 | unsigned int hxa_inflate_distance_base[30] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; 58 | const unsigned char hxa_inflate_code_length[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 59 | 60 | typedef struct { 61 | unsigned short table[16]; 62 | unsigned short translation[288]; 63 | }HXAInflateTree; 64 | 65 | static int hxa_tree_lookup(HxAInflateBitStream *stream, HXAInflateTree *tree) 66 | { 67 | int sum = 0, cur = 0, length = 0; 68 | while(TRUE) 69 | { 70 | cur = 2 * cur + hxa_inflate_read_bits(stream, 1); 71 | ++length; 72 | sum += tree->table[length]; 73 | cur -= tree->table[length]; 74 | if(cur < 0) 75 | break; 76 | } 77 | return tree->translation[sum + cur]; 78 | } 79 | 80 | static void hxa_inflate_build_default_tree(HXAInflateTree *lt, HXAInflateTree *dt) 81 | { 82 | unsigned int i; 83 | for(i = 0; i < 7; i++) 84 | lt->table[i] = 0; 85 | lt->table[7] = 24; 86 | lt->table[8] = 152; 87 | lt->table[9] = 112; 88 | for(i = 0; i < 24; i++) 89 | lt->translation[i] = 256 + i; 90 | for(i = 0; i < 144; i++) 91 | lt->translation[24 + i] = i; 92 | for(i = 0; i < 8; i++) 93 | lt->translation[24 + 144 + i] = 280 + i; 94 | for(i = 0; i < 112; i++) 95 | lt->translation[24 + 144 + 8 + i] = 144 + i; 96 | 97 | for(i = 0; i < 5; i++) 98 | dt->table[i] = 0; 99 | dt->table[5] = 32; 100 | for(i = 0; i < 32; i++) 101 | dt->translation[i] = i; 102 | } 103 | 104 | static void hxa_inflate_build_tree(HXAInflateTree *tree, const unsigned char *lengths, unsigned int count) 105 | { 106 | unsigned int offsets[16]; 107 | unsigned int i, sum; 108 | 109 | for(i = 0; i < 16; i++) 110 | tree->table[i] = 0; 111 | 112 | for(i = 0; i < count; i++) 113 | tree->table[lengths[i]]++; 114 | tree->table[0] = 0; 115 | 116 | for(sum = 0, i = 0; i < 16; i++) 117 | { 118 | offsets[i] = sum; 119 | sum += tree->table[i]; 120 | } 121 | for(i = 0; i < count; i++) 122 | if(lengths[i]) 123 | tree->translation[offsets[lengths[i]]++] = i; 124 | } 125 | 126 | static void hxa_inflate_decode_tree(HxAInflateBitStream *stream, HXAInflateTree *lt, HXAInflateTree *dt) 127 | { 128 | HXAInflateTree code_tree; 129 | unsigned char lengths[288 + 32]; 130 | unsigned int hlit, hdist, hclen; 131 | unsigned int i, count, length, previous, symbol; 132 | 133 | /* get 5 bits HLIT (257-286) */ 134 | hlit = hxa_inflate_read_bits(stream, 5) + 257; 135 | 136 | /* get 5 bits HDIST (1-32) */ 137 | hdist = hxa_inflate_read_bits(stream, 5) + 1; 138 | 139 | /* get 4 bits HCLEN (4-19) */ 140 | hclen = hxa_inflate_read_bits(stream, 4) + 4; 141 | 142 | for(i = 0; i < 19; i++) 143 | lengths[i] = 0; 144 | 145 | /* read code lengths for code length alphabet */ 146 | for(i = 0; i < hclen; ++i) 147 | lengths[hxa_inflate_code_length[i]] = hxa_inflate_read_bits(stream, 3);/* get 3 bits code length (0-7) */ 148 | 149 | 150 | /* build code length tree */ 151 | hxa_inflate_build_tree(&code_tree, lengths, 19); 152 | 153 | /* decode code lengths for the dynamic trees */ 154 | for(count = 0; count < hlit + hdist;) 155 | { 156 | symbol = hxa_tree_lookup(stream, &code_tree); 157 | if(symbol >= 16) 158 | { 159 | switch((symbol - 16) % 4) 160 | { 161 | case 0: 162 | previous = lengths[count - 1]; 163 | length = hxa_inflate_read_bits(stream, 2) + 3; 164 | for(i = 0; i < length; i++) 165 | lengths[count++] = previous; 166 | break; 167 | case 1: 168 | length = hxa_inflate_read_bits(stream, 3) + 3; 169 | for(i = 0; i < length; i++) 170 | lengths[count++] = 0; 171 | break; 172 | case 2: 173 | length = hxa_inflate_read_bits(stream, 7) + 11; 174 | for(i = 0; i < length; i++) 175 | lengths[count++] = 0; 176 | break; 177 | } 178 | }else 179 | lengths[count++] = symbol; 180 | } 181 | 182 | /* build dynamic trees */ 183 | hxa_inflate_build_tree(lt, lengths, hlit); 184 | hxa_inflate_build_tree(dt, lengths + hlit, hdist); 185 | } 186 | 187 | 188 | int hxa_inflate_decode(HxAInflateBitStream *stream, unsigned char *output, size_t *output_length, HXAInflateTree *lt, HXAInflateTree *dt) 189 | { 190 | unsigned int i, value, length, distance, offset; 191 | for(value = hxa_tree_lookup(stream, lt); value != 256; value = hxa_tree_lookup(stream, lt)) 192 | { 193 | if(value < 256) 194 | output[(*output_length)++] = value; 195 | else if(value > 288) 196 | { 197 | printf("HxA Error: Deflate error. Compressed block has length that is out of bounds.\n"); 198 | return FALSE; 199 | }else 200 | { 201 | value -= 257; 202 | length = hxa_inflate_read_bits(stream, hxa_inflate_length_bits[value]) + hxa_inflate_length_base[value]; 203 | distance = hxa_tree_lookup(stream, dt); 204 | offset = hxa_inflate_read_bits(stream, hxa_inflate_distance_bits[distance]) + hxa_inflate_distance_base[distance]; 205 | if(offset >= length) 206 | memcpy(&output[*output_length], &output[*output_length - offset], length); 207 | else 208 | for(i = 0; i < length; ++i) 209 | output[*output_length + i] = output[*output_length + i - offset]; 210 | *output_length += length; 211 | } 212 | } 213 | return TRUE; 214 | } 215 | 216 | int hxa_inflate(unsigned char *output, size_t *output_length, unsigned char *input, size_t input_length) 217 | { 218 | HXAInflateTree lt, dt; 219 | HxAInflateBitStream stream; 220 | unsigned int end = FALSE, code; 221 | stream.stream = input; 222 | stream.end = input + input_length; 223 | stream.bit = 0; 224 | *output_length = 0; 225 | hxa_inflate_build_default_tree(<, &dt); 226 | while(!end) 227 | { 228 | end = hxa_inflate_read_bits(&stream, 1); 229 | code = hxa_inflate_read_bits(&stream, 2); 230 | switch(code % 4) 231 | { 232 | case 0 : 233 | if(!hxa_inflate_uncompressed(&stream, output, output_length)) 234 | return FALSE; 235 | break; 236 | case 1 : 237 | if(!hxa_inflate_decode(&stream, output, output_length, <, &dt)) 238 | return FALSE; 239 | break; 240 | case 2 : 241 | { 242 | HXAInflateTree dynamic_lt, dynamic_dt; 243 | hxa_inflate_decode_tree(&stream, &dynamic_lt, &dynamic_dt); 244 | if(!hxa_inflate_decode(&stream, output, output_length, &dynamic_lt, &dynamic_dt)) 245 | return FALSE; 246 | } 247 | break; 248 | case 3 : 249 | printf("HxA Error: Deflate error. Code 3.\n"); 250 | return FALSE; 251 | } 252 | } 253 | return TRUE; 254 | } -------------------------------------------------------------------------------- /hxa_upi_host.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "hxa_upi.h" 6 | #ifdef _WIN32 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define HXA_UPI_DEBUG_PRINT 14 | #define HXA_UPI_WINDOWS_PATH_LENGHT_MAX (256 * 128 - 1) 15 | 16 | #undef UNICODE 17 | 18 | #ifdef UNICODE 19 | #define hxa_upi_internal_lib_load LoadLibraryW 20 | #else 21 | #define hxa_upi_internal_lib_load LoadLibraryA 22 | #endif 23 | #define hxa_upi_internal_lib_get_address GetProcAddress 24 | #define hxa_upi_internal_lib_unload FreeLibrary 25 | #else 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #define hxa_upi_internal_lib_load(a) dlopen(a, RTLD_LAZY); 32 | #define hxa_upi_internal_lib_get_address dlsym 33 | #define hxa_upi_internal_lib_unload dlclose 34 | #endif 35 | typedef unsigned int uint; 36 | 37 | HxAUPIPlugin *hxa_upi_host_temp_loaded_plugins = NULL; 38 | unsigned int hxa_upi_host_temp_loaded_plugin_count = 0; 39 | void *hxa_upi_host_temp_loaded_library = NULL; 40 | 41 | 42 | #define HXA_UPI_NXT 0x80 43 | #define HXA_UPI_SEQ2 0xc0 44 | #define HXA_UPI_SEQ3 0xe0 45 | #define HXA_UPI_SEQ4 0xf0 46 | #define HXA_UPI_SEQ5 0xf8 47 | #define HXA_UPI_SEQ6 0xfc 48 | #define HXA_UPI_BOM 0xfeff 49 | 50 | unsigned int hxa_upi_utf8_to_uint32(char *c, uint *pos) 51 | { 52 | uint i, bits, character_count = 1, high; 53 | unsigned int out; 54 | 55 | if((c[*pos] & 0x80) == 0) 56 | high = (wchar_t)c[*pos]; 57 | else if((c[*pos] & 0xe0) == HXA_UPI_SEQ2) 58 | { 59 | character_count = 2; 60 | high = (wchar_t)(c[*pos] & 0x1f); 61 | }else if((c[*pos] & 0xf0) == HXA_UPI_SEQ3) 62 | { 63 | character_count = 3; 64 | high = (wchar_t)(c[*pos] & 0x0f); 65 | }else if((c[*pos] & 0xf8) == HXA_UPI_SEQ4) 66 | { 67 | character_count = 4; 68 | high = (wchar_t)(c[*pos] & 0x07); 69 | }else if((c[*pos] & 0xfc) == HXA_UPI_SEQ5) 70 | { 71 | character_count = 5; 72 | high = (wchar_t)(c[*pos] & 0x03); 73 | }else if((c[*pos] & 0xfe) == HXA_UPI_SEQ6) 74 | { 75 | character_count = 6; 76 | high = (wchar_t)(c[*pos] & 0x01); 77 | }else 78 | { 79 | (*pos)++; 80 | return 0; 81 | } 82 | out = 0; 83 | bits = 0; 84 | for(i = 1; i < character_count; i++) 85 | { 86 | out |= (wchar_t)(c[character_count - i] & 0x3f) << bits; 87 | bits += 6; /* 6 low bits in every byte */ 88 | } 89 | out |= high << bits; 90 | (*pos) += character_count; 91 | return out; 92 | } 93 | 94 | uint hxa_upi_uint32_to_utf8(unsigned int character, char *out) 95 | { 96 | unsigned char bytes[4]; 97 | bytes[0] = (character >> 24) & 0xFF; 98 | bytes[1] = (character >> 16) & 0xFF; 99 | bytes[2] = (character >> 8) & 0xFF; 100 | bytes[3] = character & 0xFF; 101 | if(character <= 0x0000007f) 102 | { 103 | out[0] = bytes[3]; 104 | return 1; 105 | }else if(character <= 0x000007ff) 106 | { 107 | out[1] = HXA_UPI_NXT | bytes[3] & 0x3f; 108 | out[0] = HXA_UPI_SEQ2 | (bytes[3] >> 6) | ((bytes[2] & 0x07) << 2); 109 | return 2; 110 | }else if(character <= 0x0000ffff) 111 | { 112 | out[2] = HXA_UPI_NXT | bytes[3] & 0x3f; 113 | out[1] = HXA_UPI_NXT | (bytes[3] >> 6) | ((bytes[2] & 0x0f) << 2); 114 | out[0] = HXA_UPI_SEQ3 | ((bytes[2] & 0xf0) >> 4); 115 | return 3; 116 | }else if(character <= 0x001fffff) 117 | { 118 | out[3] = HXA_UPI_NXT | bytes[3] & 0x3f; 119 | out[2] = HXA_UPI_NXT | (bytes[3] >> 6) | ((bytes[2] & 0x0f) << 2); 120 | out[1] = HXA_UPI_NXT | ((bytes[2] & 0xf0) >> 4) | ((bytes[1] & 0x03) << 4); 121 | out[0] = HXA_UPI_SEQ4 | ((bytes[1] & 0x1f) >> 2); 122 | return 4; 123 | }else if(character <= 0x03ffffff) 124 | { 125 | out[4] = HXA_UPI_NXT | bytes[3] & 0x3f; 126 | out[3] = HXA_UPI_NXT | (bytes[3] >> 6) | ((bytes[2] & 0x0f) << 2); 127 | out[2] = HXA_UPI_NXT | ((bytes[2] & 0xf0) >> 4) | ((bytes[1] & 0x03) << 4); 128 | out[1] = HXA_UPI_NXT | (bytes[1] >> 2); 129 | out[0] = HXA_UPI_SEQ5 | bytes[0] & 0x03; 130 | return 5; 131 | }else /* if (*w <= 0x7fffffff) */ 132 | { 133 | out[5] = HXA_UPI_NXT | bytes[3] & 0x3f; 134 | out[4] = HXA_UPI_NXT | (bytes[3] >> 6) | ((bytes[2] & 0x0f) << 2); 135 | out[3] = HXA_UPI_NXT | (bytes[2] >> 4) | ((bytes[1] & 0x03) << 4); 136 | out[2] = HXA_UPI_NXT | (bytes[1] >> 2); 137 | out[1] = HXA_UPI_NXT | bytes[0] & 0x3f; 138 | out[0] = HXA_UPI_SEQ6 | ((bytes[0] & 0x40) >> 6); 139 | return 6; 140 | } 141 | } 142 | 143 | 144 | void hxa_upi_host_register_func(HxAUPIPlugin *plugin) 145 | { 146 | if(hxa_upi_host_temp_loaded_plugin_count % 16 == 0) 147 | hxa_upi_host_temp_loaded_plugins = realloc(hxa_upi_host_temp_loaded_plugins, (sizeof *hxa_upi_host_temp_loaded_plugins) * (hxa_upi_host_temp_loaded_plugin_count + 16)); 148 | hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count] = *plugin; 149 | hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].params = malloc((sizeof *plugin->params) * plugin->param_count); 150 | memcpy(hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].params, plugin->params, (sizeof *plugin->params) * plugin->param_count); 151 | hxa_upi_host_temp_loaded_plugins[hxa_upi_host_temp_loaded_plugin_count].library = hxa_upi_host_temp_loaded_library; 152 | hxa_upi_host_temp_loaded_plugin_count++; 153 | } 154 | 155 | void hxa_upi_host_load_library_internal(char *path) 156 | { 157 | void (*hxa_upi_plugin_library_initialize)(void (*register_func)(HxAUPIPlugin *plugin)); 158 | char *name; 159 | unsigned int i, pre_count; 160 | #ifdef UNICODE 161 | short u_path[1025]; 162 | for(i = 0; i < 1024 && path[i] !=0 ; i++) 163 | u_path[i] = (char)path[i]; 164 | u_path[i] = 0; 165 | hxa_temp_loaded_library = hxa_upi_internal_lib_load(u_path); 166 | #else 167 | hxa_upi_host_temp_loaded_library = hxa_upi_internal_lib_load(path); 168 | #endif 169 | if(hxa_upi_host_temp_loaded_library == NULL) 170 | { 171 | #ifdef HXA_UPI_DEBUG_PRINT 172 | #ifdef _WIN32 173 | printf("HxA UPI ERROR: library %s not found. Windows error code: %u\n", path, GetLastError()); 174 | #else 175 | printf("HxA UPI ERROR: library %s not found.\n", path); 176 | #endif 177 | #endif 178 | return NULL; 179 | } 180 | #ifdef WIN32 181 | hxa_upi_plugin_library_initialize = (char *(*)(void))GetProcAddress(hxa_upi_host_temp_loaded_library, "hxa_upi_plugin_library_initialize"); 182 | #else 183 | hxa_upi_plugin_library_initialize = dlsym(hxa_upi_host_temp_loaded_library, "hxa_upi_plugin_library_initialize"); 184 | #endif 185 | if(hxa_upi_plugin_library_initialize == NULL) 186 | { 187 | #ifdef HXA_UPI_DEBUG_PRINT 188 | printf("HxA UPI ERROR: imagine_lib_main not found in %s.\n", path); 189 | #endif 190 | hxa_upi_internal_lib_unload(hxa_upi_host_temp_loaded_library); 191 | return NULL; 192 | } 193 | pre_count = hxa_upi_host_temp_loaded_plugin_count; 194 | hxa_upi_plugin_library_initialize(hxa_upi_host_register_func); 195 | if(pre_count == hxa_upi_host_temp_loaded_plugin_count) 196 | hxa_upi_internal_lib_unload(hxa_upi_host_temp_loaded_library); 197 | } 198 | 199 | 200 | 201 | void hxa_upi_host_unload_library(char *path, HxAUPIPlugin *plugins, unsigned int plugin_count) 202 | { 203 | uint i, j; 204 | for(i = 0; i < plugin_count; i++) 205 | { 206 | free(plugins[i].params); 207 | if(i == 0 || plugins[i].library != plugins[i - 1].library) 208 | hxa_upi_internal_lib_unload(plugins[i - 1].library); 209 | } 210 | free(plugins); 211 | } 212 | 213 | HxAUPIPlugin *hxa_upi_host_load_library(char *path, unsigned int *plugin_count) 214 | { 215 | hxa_upi_host_temp_loaded_plugins = NULL; 216 | hxa_upi_host_temp_loaded_plugin_count = 0; 217 | hxa_upi_host_load_library_internal(path); 218 | *plugin_count = hxa_upi_host_temp_loaded_plugin_count; 219 | return hxa_upi_host_temp_loaded_plugins; 220 | } 221 | 222 | 223 | #ifdef _WIN32 224 | /* implement path searching for windows */ 225 | typedef struct{ 226 | char d_name[HXA_UPI_WINDOWS_PATH_LENGHT_MAX]; 227 | }idirent; 228 | 229 | typedef struct{ 230 | WIN32_FIND_DATAW data; 231 | HANDLE handle; 232 | idirent ent; 233 | }DIR; 234 | 235 | DIR *hxa_upi_opendir(char *path) 236 | { 237 | DIR *dir; 238 | unsigned int pos, i; 239 | WIN32_FIND_DATAW data; 240 | HANDLE handle; 241 | wchar_t unicode_path[HXA_UPI_WINDOWS_PATH_LENGHT_MAX]; 242 | char *post_fix = "\\*.*"; 243 | if(path == NULL) 244 | { 245 | unicode_path[0] = "."; 246 | unicode_path[1] = 0; 247 | }else 248 | { 249 | for(i = pos = 0; i < HXA_UPI_WINDOWS_PATH_LENGHT_MAX - 5 && path[pos] != 0; i++) 250 | unicode_path[i] = hxa_upi_utf8_to_uint32(path, &pos); 251 | } 252 | for(pos = 0; post_fix[pos] != 0; i++) 253 | unicode_path[i] = (wchar_t)post_fix[pos++]; 254 | unicode_path[i] = 0; 255 | if((handle = FindFirstFileW(unicode_path, &data)) != INVALID_HANDLE_VALUE) 256 | { 257 | dir = malloc(sizeof *dir); 258 | dir->handle = handle; 259 | dir->data = data; 260 | dir->ent.d_name[0] = 0; 261 | return dir; 262 | } 263 | return NULL; 264 | } 265 | 266 | void hxa_upi_closedir(DIR *dir) 267 | { 268 | FindClose(dir->handle); 269 | free(dir); 270 | } 271 | 272 | idirent *hxa_upi_readdir(DIR *dir) 273 | { 274 | uint i, pos; 275 | if(FindNextFileW(dir->handle, &dir->data) != TRUE) 276 | return NULL; 277 | for(i = pos = 0; dir->data.cFileName[i] != 0 && pos < HXA_UPI_WINDOWS_PATH_LENGHT_MAX - 6; i++) 278 | pos += hxa_upi_uint32_to_utf8(dir->data.cFileName[i], &dir->ent.d_name[pos]); 279 | dir->ent.d_name[pos] = 0; 280 | return &dir->ent; 281 | 282 | } 283 | 284 | #else 285 | /* use unix APIs */ 286 | #define idirent struct dirent 287 | #define hxa_upi_opendir opendir; 288 | #define hxa_upi_closedir closedir 289 | #define hxa_upi_readdir readdir 290 | #endif 291 | 292 | int hxa_upi_host_filter(char *path, char *filter) 293 | { 294 | unsigned int i, j; 295 | for(i = 0; path[i] != 0; i++) 296 | { 297 | for(j = 0; path[i + j] != 0 && filter[j] != 0 && (filter[j] == path[i + j] || filter[j] + 32 == path[i + j]); j++); 298 | if(filter[j] == 0) 299 | return TRUE; 300 | } 301 | return FALSE; 302 | } 303 | 304 | HxAUPIPlugin *hxa_upi_host_load_directory(char *path, unsigned int *plugin_count) 305 | { 306 | DIR *d; 307 | idirent *ent; 308 | char p[1024]; 309 | unsigned int i, start; 310 | hxa_upi_host_temp_loaded_plugins = NULL; 311 | hxa_upi_host_temp_loaded_plugin_count = 0; 312 | for(start = 0; start < 1024 - 1 && path[start] != 0; start++) 313 | p[start] = path[start]; 314 | d = hxa_upi_opendir(path); 315 | if(d != NULL) 316 | { 317 | ent = hxa_upi_readdir(d); 318 | if(ent != NULL) 319 | { 320 | while(TRUE) 321 | { 322 | if(hxa_upi_host_filter(ent->d_name, ".DLL") || 323 | hxa_upi_host_filter(ent->d_name, ".SO") || 324 | hxa_upi_host_filter(ent->d_name, ".LIB")) 325 | { 326 | for(i = 0; i + start < 1024 - 1 && ent->d_name[i] != 0; i++) 327 | p[start + i] = ent->d_name[i]; 328 | if(i + start < 1024 - 1) 329 | { 330 | p[start + i] = 0; 331 | hxa_upi_host_load_library_internal(p); 332 | } 333 | } 334 | ent = hxa_upi_readdir(d); 335 | if(ent == NULL) 336 | break; 337 | } 338 | } 339 | hxa_upi_closedir(d); 340 | } 341 | *plugin_count = hxa_upi_host_temp_loaded_plugin_count; 342 | return hxa_upi_host_temp_loaded_plugins; 343 | } 344 | -------------------------------------------------------------------------------- /hxa_util_close.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "hxa.h" 6 | #include "hxa_utils.h" 7 | 8 | typedef struct{ 9 | unsigned int edge; 10 | unsigned int original; 11 | float value; 12 | void *next; 13 | void *previous; 14 | }HxAHoleEdge; 15 | 16 | float un_hole_vector_normalized3f(float *vec, float *start, float *end) 17 | { 18 | float f; 19 | vec[0] = end[0] - start[0]; 20 | vec[1] = end[1] - start[1]; 21 | vec[2] = end[2] - start[2]; 22 | f = sqrtf(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]); 23 | vec[0] /= f; 24 | vec[1] /= f; 25 | vec[2] /= f; 26 | return f; 27 | } 28 | 29 | void un_hole_normal3f(float *output, float *a, float *b, float *c) 30 | { 31 | float a2[3], b2[3], f; 32 | a2[0] = a[0] - c[0]; 33 | a2[1] = a[1] - c[1]; 34 | a2[2] = a[2] - c[2]; 35 | b2[0] = b[0] - c[0]; 36 | b2[1] = b[1] - c[1]; 37 | b2[2] = b[2] - c[2]; 38 | f = sqrtf(a2[0] * a2[0] + a2[1] * a2[1] + a2[2] * a2[2]); 39 | a2[0] /= f; 40 | a2[1] /= f; 41 | a2[2] /= f; 42 | f = sqrtf(b2[0] * b2[0] + b2[1] * b2[1] + b2[2] * b2[2]); 43 | b2[0] /= f; 44 | b2[1] /= f; 45 | b2[2] /= f; 46 | output[0] = a2[1] * b2[2] - a2[2] * b2[1]; 47 | output[1] = a2[2] * b2[0] - a2[0] * b2[2]; 48 | output[2] = a2[0] * b2[1] - a2[1] * b2[0]; 49 | f = sqrtf(output[0] * output[0] + output[1] * output[1] + output[2] * output[2]); 50 | output[0] /= f; 51 | output[1] /= f; 52 | output[2] /= f; 53 | } 54 | 55 | float un_hole_edge_length(int *ref, float *vertex, unsigned int edge) 56 | { 57 | float vec[3]; 58 | int v1, v2; 59 | v1 = ref[edge]; 60 | if(v1 < 0) 61 | v1 = -1 - v1; 62 | edge = hxa_corner_get_next(ref, edge); 63 | v2 = ref[edge]; 64 | if(v2 < 0) 65 | v2 = -1 - v2; 66 | v1 *= 3; 67 | v2 *= 3; 68 | vec[0] = vertex[v1 + 0] - vertex[v2 + 0]; 69 | vec[1] = vertex[v1 + 1] - vertex[v2 + 1]; 70 | vec[2] = vertex[v1 + 2] - vertex[v2 + 2]; 71 | return vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]; 72 | } 73 | 74 | 75 | float un_hole_edge_rate(int *ref, float *vertex, unsigned int *neighbour, unsigned int edge_a, unsigned int edge_b, unsigned int edge_c) 76 | { 77 | float n[3], n2[3], f, v0[3], v1[3]; 78 | unsigned int next; 79 | int vr[4]; 80 | vr[0] = (hxa_ref(ref, edge_a)) * 3; 81 | vr[1] = (hxa_ref(ref, edge_b)) * 3; 82 | vr[2] = (hxa_ref(ref, edge_c)) * 3; 83 | un_hole_normal3f(n, &vertex[vr[1]], &vertex[vr[0]], &vertex[vr[2]]); 84 | next = hxa_corner_get_previous(ref, edge_a); 85 | vr[3] = (hxa_ref(ref, next)) * 3; 86 | un_hole_normal3f(n2, &vertex[vr[0]], &vertex[vr[1]], &vertex[vr[3]]); 87 | 88 | f = 1.0 + n[0] * n2[0] + n[1] * n2[1] + n[2] * n2[2]; 89 | if(f != f) 90 | f = 0.1; 91 | next = hxa_corner_get_previous(ref, edge_b); 92 | vr[3] = (hxa_ref(ref, next)) * 3; 93 | un_hole_normal3f(n2, &vertex[vr[1]], &vertex[vr[2]], &vertex[vr[3]]); 94 | f *= 1.0 + n[0] * n2[0] + n[1] * n2[1] + n[2] * n2[2]; 95 | if(f != f) 96 | f = 0.1; 97 | un_hole_vector_normalized3f(v0, &vertex[vr[1]], &vertex[vr[0]]); 98 | un_hole_vector_normalized3f(v1, &vertex[vr[1]], &vertex[vr[2]]); 99 | f *= 1.0 + v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2]; 100 | if(f != f) 101 | f = 0.0; 102 | return f; 103 | } 104 | 105 | unsigned int hxa_hole_close_one(int *ref, unsigned int ref_length, float *vertex_array, unsigned int *neighbour, unsigned int edge, HxAHoleEdge *buffer) 106 | { 107 | HxAHoleEdge *start, *next, *found; 108 | unsigned int i, count = 0; 109 | i = edge; 110 | while(1) 111 | { 112 | buffer[count].edge = i; 113 | buffer[count].original = i; 114 | buffer[count].next = &buffer[count + 1]; 115 | buffer[count].previous = &buffer[count - 1]; 116 | i = hxa_edge_get_next(ref, neighbour, i); 117 | count++; 118 | if(i == edge) 119 | break; 120 | } 121 | buffer[count - 1].next = &buffer[0]; 122 | buffer[0].previous = &buffer[count - 1]; 123 | 124 | for(i = 0; i < count; i++) 125 | { 126 | buffer[i].value = un_hole_edge_rate(ref, vertex_array, neighbour, buffer[i].edge, buffer[(i + 1) % count].edge, buffer[(i + 2) % count].edge); 127 | 128 | } 129 | start = buffer; 130 | 131 | 132 | while(count != 0) 133 | { 134 | found = start; 135 | for(next = start->next; next != start; next = next->next) 136 | if(found->value < next->value) 137 | found = next; 138 | 139 | 140 | next = found->next; 141 | ref[ref_length + 0] = hxa_ref(ref, found->edge); 142 | ref[ref_length + 1] = hxa_ref(ref, ((HxAHoleEdge *)next->next)->edge); 143 | ref[ref_length + 2] = -hxa_ref(ref, next->edge) - 1; 144 | 145 | neighbour[ref_length + 1] = next->edge; 146 | neighbour[ref_length + 2] = found->edge; 147 | 148 | neighbour[next->edge] = ref_length + 1; 149 | neighbour[found->edge] = ref_length + 2; 150 | 151 | if(count == 3) 152 | { 153 | neighbour[ref_length] = ((HxAHoleEdge *)next->next)->edge; 154 | neighbour[((HxAHoleEdge *)next->next)->edge] = ref_length; 155 | return ref_length + 3; 156 | }else 157 | neighbour[ref_length] = -1; 158 | if(count == 3) 159 | break; 160 | 161 | 162 | found->next = ((HxAHoleEdge *)found->next)->next; 163 | ((HxAHoleEdge *)found->next)->previous = found; 164 | found->edge = ref_length; 165 | found->value = un_hole_edge_rate(ref, vertex_array, neighbour, found->edge, ((HxAHoleEdge *)found->next)->edge, ((HxAHoleEdge *)((HxAHoleEdge *)found->next)->next)->edge); 166 | ((HxAHoleEdge *)found->previous)->value = un_hole_edge_rate(ref, vertex_array, neighbour, ((HxAHoleEdge *)found->previous)->edge, found->edge, ((HxAHoleEdge *)found->next)->edge); 167 | if(un_hole_edge_length(ref, vertex_array, ref_length + 1) < un_hole_edge_length(ref, vertex_array, ref_length + 2)) 168 | found->value *= 0.95; 169 | else 170 | ((HxAHoleEdge *)found->previous)->value *= 0.95; 171 | ref_length += 3; 172 | start = found; 173 | count--; 174 | } 175 | return ref_length; 176 | } 177 | 178 | 179 | 180 | void hxa_close_node_extend_layer(HXALayer *layer, unsigned int last_length, unsigned int new_length) 181 | { 182 | HXALayer l; 183 | unsigned int i, length; 184 | switch(layer->type) 185 | { 186 | case HXA_LDT_UINT8 : 187 | length = (sizeof *l.data.uint8_data) * last_length * layer->components; 188 | l.data.uint8_data = malloc(length); 189 | memcpy(l.data.uint8_data, layer->data.uint8_data, length); 190 | length = new_length * layer->components; 191 | for(i = new_length * layer->components; i < length; i++) 192 | l.data.uint8_data[i] = 0; 193 | free(layer->data.uint8_data); 194 | layer->data.uint8_data = l.data.uint8_data; 195 | break; 196 | case HXA_LDT_INT32 : 197 | length = (sizeof *l.data.int32_data) * last_length * layer->components; 198 | l.data.int32_data = malloc(length); 199 | memcpy(l.data.int32_data, layer->data.int32_data, length); 200 | length = new_length * layer->components; 201 | for(i = new_length * layer->components; i < length; i++) 202 | l.data.int32_data[i] = 0; 203 | free(layer->data.int32_data); 204 | layer->data.int32_data = l.data.int32_data; 205 | break; 206 | case HXA_LDT_FLOAT : 207 | length = (sizeof *l.data.float_data) * last_length * layer->components; 208 | l.data.float_data = malloc(length); 209 | memcpy(l.data.float_data, layer->data.float_data, length); 210 | length = new_length * layer->components; 211 | for(i = new_length * layer->components; i < length; i++) 212 | l.data.float_data[i] = 0; 213 | free(layer->data.float_data); 214 | layer->data.float_data = l.data.float_data; 215 | break; 216 | case HXA_LDT_DOUBLE : 217 | length = (sizeof *l.data.double_data) * last_length * layer->components; 218 | l.data.double_data = malloc(length); 219 | memcpy(l.data.double_data, layer->data.double_data, length); 220 | length = new_length * layer->components; 221 | for(i = new_length * layer->components; i < length; i++) 222 | l.data.double_data[i] = 0; 223 | free(layer->data.double_data); 224 | layer->data.double_data = l.data.double_data; 225 | break; 226 | } 227 | } 228 | 229 | void hxa_close_node(HXANode *node) 230 | { 231 | char *name = HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME; 232 | HxAHoleEdge *edge_buffer; 233 | float *vertex_array; 234 | unsigned int i, j, count, *n, *n2; 235 | signed int *ref; 236 | if(node->type != HXA_NT_GEOMETRY || node->content.geometry.vertex_count == 0 || node->content.geometry.edge_corner_count == 0) 237 | return; 238 | 239 | n = hxa_neighbour_node(node); 240 | for(count = i = 0; i < node->content.geometry.edge_corner_count; i++) 241 | if(n[i] == -1) 242 | count++; 243 | if(count == 0) 244 | { 245 | free(n); 246 | return; 247 | } 248 | ref = malloc((sizeof *ref) * (node->content.geometry.edge_corner_count + count * 3)); 249 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 250 | { 251 | ref[i] = node->content.geometry.corner_stack.layers[0].data.int32_data[i]; 252 | } 253 | n2 = malloc((sizeof *ref) * (node->content.geometry.edge_corner_count + count * 3)); 254 | memcpy(n2, n, (sizeof *n2) * node->content.geometry.edge_corner_count); 255 | free(n); 256 | edge_buffer = malloc((sizeof *edge_buffer) * count); 257 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 258 | { 259 | count = node->content.geometry.vertex_count * 3; 260 | vertex_array = malloc((sizeof *vertex_array) * count); 261 | for(i = 0; i < count; i++) 262 | vertex_array[i] = (float)node->content.geometry.vertex_stack.layers[0].data.double_data[i]; 263 | }else 264 | vertex_array = node->content.geometry.vertex_stack.layers[0].data.float_data; 265 | 266 | count = node->content.geometry.edge_corner_count; 267 | for(i = 0; i < node->content.geometry.edge_corner_count; i++) 268 | if(n2[i] == -1) 269 | count = hxa_hole_close_one(ref, count, vertex_array, n2, i, edge_buffer); 270 | 271 | free(node->content.geometry.corner_stack.layers->data.int32_data); 272 | node->content.geometry.corner_stack.layers->data.int32_data = ref; 273 | for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++) 274 | hxa_close_node_extend_layer(&node->content.geometry.corner_stack.layers[i], node->content.geometry.edge_corner_count, count); 275 | for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++) 276 | { 277 | for(j = 0; name[j] == node->content.geometry.corner_stack.layers[i].name[j] && 0 != node->content.geometry.corner_stack.layers[i].name[j]; j++); 278 | if(name[j] == node->content.geometry.corner_stack.layers[i].name[j]) 279 | { 280 | memcpy(node->content.geometry.corner_stack.layers[i].data.int32_data, n2, sizeof(hxa_int32) * count); 281 | }else 282 | hxa_close_node_extend_layer(&node->content.geometry.edge_stack.layers[i], node->content.geometry.edge_corner_count, count); 283 | } 284 | for(i = 0; i < node->content.geometry.face_stack.layer_count; i++) 285 | hxa_close_node_extend_layer(&node->content.geometry.face_stack.layers[i], node->content.geometry.face_count, node->content.geometry.face_count + (count - node->content.geometry.edge_corner_count) / 3); 286 | 287 | node->content.geometry.face_count += (count - node->content.geometry.edge_corner_count) / 3; 288 | node->content.geometry.edge_corner_count = count; 289 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE) 290 | free(vertex_array); 291 | free(n2); 292 | free(edge_buffer); 293 | } 294 | 295 | 296 | 297 | void hxa_close_file(HXAFile *file) 298 | { 299 | unsigned int i; 300 | hxa_print(file, 0); 301 | for(i = 0; i < file->node_count; i++) 302 | hxa_close_node(&file->node_array[i]); 303 | hxa_print(file, 0); 304 | i = 0; 305 | } -------------------------------------------------------------------------------- /hxa_util_png.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include "hxa.h" 6 | #include "hxa_utils.h" 7 | 8 | #define FALSE 0 9 | #define TRUE !FALSE 10 | 11 | typedef enum{ 12 | HXA_PNG_CT_GRAYSCALE = 0, 13 | HXA_PNG_CT_RGB = 2, 14 | HXA_PNG_CT_INDEXED = 3, 15 | HXA_PNG_CT_GRAYSCALE_AND_ALPHA = 4, 16 | HXA_PNG_CT_RGB_AND_ALPHA = 6 17 | }HxAPNGChannelTypes; 18 | 19 | /* 20 | A palette is a 3 byte per entry list at the length of chunk. 21 | */ 22 | 23 | extern int hxa_inflate(unsigned char *output, size_t *output_length, unsigned char *input, size_t input_length); 24 | 25 | 26 | void hxa_load_unpack_uint8(unsigned char *input_buffer, unsigned char *output_buffer, unsigned int x, unsigned int y, unsigned int channels) 27 | { 28 | unsigned int i, j, read = 0, write = 0, acces_a, acces_b; 29 | unsigned char tmp[4]; 30 | if(input_buffer[read] == 2) 31 | input_buffer[read] = 0; 32 | else if(input_buffer[read] == 2) 33 | input_buffer[read] = 5; 34 | for(i = 0; i < y; i++) 35 | { 36 | switch(input_buffer[read++]) 37 | { 38 | case 0 : 39 | memcpy(&output_buffer[write], &input_buffer[read], x * channels); 40 | write += channels * x; 41 | read += channels * x; 42 | break; 43 | case 1 : 44 | acces_a = write; 45 | for(j = 0; j < channels; j++) 46 | output_buffer[write++] = input_buffer[read++]; 47 | for(; j < x * channels; j++) 48 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_a++]; 49 | break; 50 | case 2 : 51 | acces_b = write - x * channels; 52 | for(j = 0; j < x * channels; j++) 53 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_b++]; 54 | break; 55 | case 3 : 56 | acces_a = write; 57 | acces_b = write - x * channels; 58 | for(j = 0; j < channels; j++) 59 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_b++] / 2; 60 | for(; j < x * channels; j++) 61 | output_buffer[write++] = input_buffer[read++] + (output_buffer[acces_a++] + output_buffer[acces_b++]) / 2; 62 | break; 63 | case 4 : 64 | acces_a = write; 65 | acces_b = write - x * channels; 66 | for(j = 0; j < channels; j++) 67 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_b++] / 2; 68 | for(; j < x * channels; j++) 69 | output_buffer[write++] = input_buffer[read++] + (output_buffer[acces_a++] + output_buffer[acces_b++]) / 2; 70 | break; 71 | case 5 : /* First line version on read abrage of A and b */ 72 | acces_a = write; 73 | acces_b = write - x * channels; 74 | for(j = 0; j < channels; j++) 75 | output_buffer[write++] = input_buffer[read++]; 76 | for(; j < x * channels; j++) 77 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_a++] / 2; 78 | break; 79 | case 6 : 80 | acces_a = write; 81 | acces_b = write - x * channels; 82 | for(j = 0; j < channels; j++) 83 | output_buffer[write++] = input_buffer[read++] + output_buffer[acces_b++] / 2; 84 | for(; j < x * channels; j++) 85 | output_buffer[write++] = input_buffer[read++] + (output_buffer[acces_a++] + output_buffer[acces_b++]) / 2; 86 | break; 87 | } 88 | } 89 | } 90 | 91 | void hxa_load_png(HXAFile *file, char *file_name) 92 | { 93 | char *name = HXA_CONVENTION_SOFT_LAYER_COLOR; 94 | unsigned int channels[] = {1, 0, 3, 3, 2, 0, 4}; 95 | unsigned int x, y, i, j, meta_data_used = 0, packed_size = 0; 96 | unsigned char bits, compression, filter, interlace, *meta_data; 97 | HxAPNGChannelTypes color; 98 | HXANode *node; 99 | union {char text[5]; unsigned int type;}type; 100 | size_t size, pos, chunk_length, bitmap_size; 101 | unsigned char *data, *unprocessed_data, *image_data; 102 | data = f_text_load(file_name, &size); 103 | if(data == NULL) 104 | { 105 | printf("HxA Error: Could not open file %d\n", file_name); 106 | return; 107 | } 108 | type.text[4] = 0; 109 | chunk_length = data[11] + data[10] * 256 + data[9] * 256 * 256 + data[8] * 256 * 256 * 256; 110 | x = data[19] + data[18] * 256 + data[17] * 256 * 256 + data[16] * 256 * 256 * 256; 111 | y = data[23] + data[22] * 256 + data[21] * 256 * 256 + data[20] * 256 * 256 * 256; 112 | bits = data[24]; 113 | color = data[25]; 114 | compression = data[26]; // Must be 0 Deflate 115 | filter = data[27]; // Must be 0 116 | interlace = data[28]; // 0, regular 1 adam7 8 * 8 117 | 118 | meta_data = malloc(size); 119 | bitmap_size = x * y * channels[color] * bits / 8; 120 | unprocessed_data = malloc(bitmap_size + y); 121 | for(pos = 8 + 8 + chunk_length + 4; pos < size; pos += chunk_length + 12) 122 | { 123 | chunk_length = data[pos + 3] + data[pos + 2] * 256 + data[pos + 1] * 256 * 256 + data[pos] * 256 * 256 * 256; 124 | memcpy(&type.type, &data[pos + 4], 4); 125 | // printf("chunk_length %u - %s %u\n", chunk_length, type.text, type.type); 126 | if(type.type == 1413563465) 127 | { 128 | f_print_raw(data, pos + 8); 129 | exit(0); 130 | for(i = 0; i < chunk_length; i++) 131 | data[packed_size++] = data[pos + 8 + i]; 132 | /* printf("nibbles %u %u\n", data[0] % 16, data[0] / 16); 133 | printf("nibbles %u %u %u\n", data[1] % 16, (data[1] / 16) % 2, (data[1] / 32) % 8); 134 | hxa_inflate(image_data, bitmap_size, &i, data, chunk_length); 135 | f_print_raw(data, size); 136 | exit(0);*/ 137 | }else 138 | { 139 | memcpy(&meta_data[meta_data_used], &data[pos], chunk_length + 12); 140 | meta_data_used += chunk_length + 12; 141 | } 142 | } 143 | meta_data = realloc(meta_data, meta_data_used); 144 | hxa_inflate(unprocessed_data, &bitmap_size, &data[2], packed_size - 6); 145 | image_data = malloc(x * y * channels[color]); 146 | hxa_load_unpack_uint8(unprocessed_data, image_data, x, y, channels[color]); 147 | 148 | free(data); 149 | file->node_count++; 150 | file->node_array = realloc(file->node_array, (sizeof *file->node_array) * file->node_count); 151 | node = &file->node_array[file->node_count - 1]; 152 | node->type = HXA_NT_IMAGE; 153 | node->content.image.type = HXA_IT_2D_IMAGE; 154 | node->content.image.resolution[0] = x; 155 | node->content.image.resolution[1] = y; 156 | node->content.image.resolution[2] = 1; 157 | node->content.image.image_stack.layer_count = 1; 158 | node->content.image.image_stack.layers = malloc(sizeof *node->content.image.image_stack.layers); 159 | node->content.image.image_stack.layers->components = channels[color]; 160 | node->content.image.image_stack.layers->type = HXA_LDT_UINT8; 161 | node->content.image.image_stack.layers->data.uint8_data = image_data; 162 | for(i = 0; name[i] != 0; i++) 163 | node->content.image.image_stack.layers->name[i] = name[i]; 164 | node->content.image.image_stack.layers->name[i] = 0; 165 | node->meta_data_count = 2; 166 | node->meta_data = malloc((sizeof *node->meta_data) * 2); 167 | name = "name"; 168 | for(i = 0; name[i] != 0; i++) 169 | node->meta_data[0].name[i] = name[i]; 170 | node->meta_data[0].name[i] = 0; 171 | node->meta_data[0].type = HXA_MDT_TEXT; 172 | for(i = 0; file_name[i] != 0; i++); 173 | node->meta_data[0].value.text_value = malloc(i + 1); 174 | for(; i != 0 && file_name[i] != '/' && file_name[i] != '\\'; i--); 175 | if(file_name[i] == '/' || file_name[i] == '\\') 176 | i++; 177 | for(j = 0; file_name[i + j] != 0 && file_name[i + j] != '.'; j++) 178 | node->meta_data[0].value.text_value[j] = file_name[i + j]; 179 | node->meta_data[0].value.text_value[j] = 0; 180 | node->meta_data[0].array_length = j; 181 | name = "png_cunks"; 182 | for(i = 0; name[i] != 0; i++) 183 | node->meta_data[1].name[i] = name[i]; 184 | node->meta_data[1].name[i] = 0; 185 | node->meta_data[1].type = HXA_MDT_BINARY; 186 | node->meta_data[1].array_length = meta_data_used; 187 | node->meta_data[1].value.bin_value = meta_data; 188 | } 189 | 190 | /* Table of CRCs of all 8-bit messages. */ 191 | unsigned long crc_table[256]; 192 | 193 | /* Flag: has the table been computed? Initially false. */ 194 | int crc_table_computed = 0; 195 | 196 | /* Make the table for a fast CRC. */ 197 | void hxa_png_crc_compute_table(void) 198 | { 199 | unsigned long c; 200 | int n, k; 201 | 202 | for(n = 0; n < 256; n++) 203 | { 204 | c = (unsigned long)n; 205 | for(k = 0; k < 8; k++) 206 | { 207 | if(c & 1) 208 | c = 0xedb88320L ^ (c >> 1); 209 | else 210 | c = c >> 1; 211 | } 212 | crc_table[n] = c; 213 | } 214 | crc_table_computed = 1; 215 | } 216 | void hxa_png_crc_compute(unsigned char *output, unsigned char *read_buffer, int length) 217 | { 218 | unsigned int crc = 0xffffffffL, i; 219 | if(!crc_table_computed) 220 | hxa_png_crc_compute_table(); 221 | for(i = 0; i < length; i++) 222 | crc = crc_table[(crc ^ read_buffer[i]) & 0xff] ^ (i >> 8); 223 | crc = crc ^ 0xffffffffL; 224 | output[1] = (crc >> 24) & 0xFF; 225 | output[2] = (crc >> 16) & 0xFF; 226 | output[3] = (crc >> 8) & 0xFF; 227 | output[4] = crc & 0xFF; 228 | } 229 | 230 | int hxa_save_png(unsigned char *pixels, unsigned int channels, unsigned int x, unsigned int y, char *file_name) 231 | { 232 | FILE *file; 233 | unsigned int i, pixel_length, data_length, file_length, compression_left, write_pos, row_pos; 234 | unsigned short s; 235 | char *data, channel_code[] = {0, 0, 4, 2, 6}; 236 | unsigned char header[] = {137, 237 | 'P', 238 | 'N', 239 | 'G', 240 | 13, 241 | 10, 242 | 26, 243 | 10, 244 | 0, /* Chunk length */ 245 | 0, 246 | 0, 247 | 13, 248 | 'I', 249 | 'H', 250 | 'D', 251 | 'R', 252 | 0, /* size X */ 253 | 0, 254 | 0, 255 | 0, 256 | 0, /* size y */ 257 | 0, 258 | 0, 259 | 40, 260 | 8, /* bits */ 261 | 2, /* Color */ 262 | 0, /* Compression */ 263 | 0, /* Filter */ 264 | 0, 265 | 0, /* CRC */ 266 | 0, 267 | 0, 268 | 0, 269 | 0, /* Chunk length */ 270 | 0, 271 | 0, 272 | 0, 273 | 'I', /*Chunk type*/ 274 | 'D', 275 | 'A', 276 | 'T'}; /* Interlace (0 == None)*/ 277 | 278 | file = fopen(file_name, "w"); 279 | if(file == NULL) 280 | return FALSE; 281 | pixel_length = (x * channels + 1) * y; 282 | data_length = pixel_length + (1 + pixel_length / 0xFFFF) * 5; 283 | file_length = sizeof(header) + 4 + data_length; 284 | data = malloc(file_length); 285 | memcpy(data, header, sizeof(header)); 286 | data[16] = (x >> 24) & 0xFF; 287 | data[17] = (x >> 16) & 0xFF; 288 | data[18] = (x >> 8) & 0xFF; 289 | data[19] = x & 0xFF; 290 | data[20] = (y >> 24) & 0xFF; 291 | data[21] = (y >> 16) & 0xFF; 292 | data[22] = (y >> 8) & 0xFF; 293 | data[23] = y & 0xFF; 294 | data[25] = channel_code[channels]; 295 | 296 | hxa_png_crc_compute(&data[29], &data[8], 17); 297 | data[33] = (data_length >> 24) & 0xFF; 298 | data[34] = (data_length >> 16) & 0xFF; 299 | data[35] = (data_length >> 8) & 0xFF; 300 | data[36] = data_length & 0xFF; 301 | write_pos = sizeof(header); 302 | for(i = row_pos = compression_left = 0; i < y;) 303 | { 304 | if(compression_left == 0) 305 | { 306 | if((y - i) * (x * channels + 1) - row_pos > 0xFFFF) 307 | { 308 | data[write_pos++] = 0; /* uncompressed */ 309 | data[write_pos++] = 0xFF; /* length */ 310 | data[write_pos++] = 0xFF; 311 | data[write_pos++] = 0; /* inv legth */ 312 | data[write_pos++] = 0; 313 | compression_left = 0xFFFF; 314 | }else 315 | { 316 | s = (y - i) * (x * channels + 1) - row_pos; 317 | data[write_pos++] = 1; /* Last uncompressed uncompressed */ 318 | data[write_pos++] = (s >> 8) & 0xFF; /* length */ 319 | data[write_pos++] = s & 0xFF; 320 | s = ~s; 321 | data[write_pos++] = (s >> 8) & 0xFF; /* inv legth */ 322 | data[write_pos++] = s & 0xFF; 323 | compression_left = 0xFFFF; 324 | } 325 | } 326 | if(row_pos == 0) 327 | { 328 | data[write_pos++] = 0; 329 | compression_left--; 330 | }else 331 | { 332 | if(compression_left >= x * channels - row_pos) 333 | { 334 | memcpy(&data[write_pos], &pixels[i * x * channels + row_pos], x * channels - row_pos); 335 | compression_left -= x * channels - row_pos; 336 | row_pos = 0; 337 | i++; 338 | }else 339 | { 340 | memcpy(&data[write_pos], &pixels[i * x * channels + row_pos], compression_left); 341 | row_pos += compression_left; 342 | compression_left = 0; 343 | } 344 | } 345 | } 346 | hxa_png_crc_compute(&data[write_pos], &data[41], write_pos - 41); 347 | fwrite(data, 1, file_length, file); 348 | fclose(file); 349 | free(data); 350 | return TRUE; 351 | } -------------------------------------------------------------------------------- /hxa_util_type_conversion.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "forge.h" 5 | #include "hxa.h" 6 | #include "hxa_utils.h" 7 | 8 | #define _CRT_SECURE_NO_WARNINGS 9 | #pragma warning(disable:4996) 10 | #pragma warning(disable:4703) 11 | #pragma warning(disable:4996) 12 | #pragma warning(disable:4664) 13 | 14 | #define FALSE 0 15 | #define TRUE !FALSE 16 | 17 | 18 | short hxa_float32_to_float16(float value) 19 | { 20 | union{int integer; float real;}convert; 21 | int sign, exponent, sig, t, a, b; 22 | convert.real = value; 23 | 24 | sign = (convert.integer >> 16) & 0x00008000; 25 | exponent = ((convert.integer >> 23) & 0x000000ff) - (127 - 15); 26 | sig = convert.integer & 0x007fffff; 27 | 28 | if(exponent <= 0) 29 | { 30 | if(exponent < -10) 31 | return sign; 32 | sig = sig | 0x00800000; 33 | t = 14 - exponent; 34 | a = (1 << (t - 1)) - 1; 35 | b = (sig >> t) & 1; 36 | 37 | sig = (sig + a + b) >> t; 38 | return sign | sig; 39 | }else if(exponent == 0xff - (127 - 15)) 40 | { 41 | if(sig == 0) 42 | return sign | 0x7c00; 43 | else 44 | { 45 | sig >>= 13; 46 | return sign | 0x7c00 | sig | (sig == 0); 47 | } 48 | }else 49 | { 50 | sig = sig + 0x00000fff + ((sig >> 13) & 1); 51 | 52 | if(sig & 0x00800000) 53 | { 54 | sig = 0; 55 | exponent += 1; 56 | } 57 | if (exponent > 30) 58 | return sign | 0x7c00; /*inf*/ 59 | return sign | (exponent << 10) | (sig >> 13); 60 | } 61 | } 62 | 63 | char *export_type_strings[] = {"char", "unsigned char", "short", "unsigned short", "int", "unsigned int", "unsigned short", "float", "double"}; 64 | char *export_type_names[] = {"int8", "uint8", "int16", "uint16", "int32", "uint32", "half16", "float32", "double64"}; 65 | char *export_type_enum_names[] = {"uint8_data", "int32_data", "float_data", "double_data"}; 66 | long long export_type_scale[] = {127, 255, (256 * 128 - 1), (256 * 256 - 1), (256 * 256 * 256 * 128 - 1), (256 * 256 * 256 * 256 - 1)}; 67 | long long export_type_min[] = {-127, 0, -(256 * 128 - 1), 0, -(256 * 256 * 256 * 128 - 1), 0, -(256 * 256 * 256 * 256), -(256 * 256 * 256 * 256), -(256 * 256 * 256 * 256)}; 68 | long long export_type_max[] = {127, 255, (256 * 128 - 1), (256 * 256 - 1), (256 * 256 * 256 * 128 - 1), (256 * 256 * 256 * 256 - 1), (256 * 256 * 256 * 256), (256 * 256 * 256 * 256), (256 * 256 * 256 * 256)}; 69 | 70 | void hxa_type_convert_gen() 71 | { 72 | unsigned int i, j, k, l, layer_data_types[HXA_LDT_COUNT] = {HXA_UAET_UINT8, HXA_UAET_INT32, HXA_UAET_FLOAT32, HXA_UAET_DOUBLE64}; 73 | char *stack_names[] = {"vertex_stack", "corner_stack", "face_stack"}; 74 | FILE *f; 75 | f = fopen("hxa_convesion_generated.c", "w"); 76 | fprintf(f, "#include \"hxa.h\"\n"); 77 | fprintf(f, "#include \"hxa_utils.h\"\n\n"); 78 | fprintf(f, "#define NULL (void *)0\n\n"); 79 | fprintf(f, "unsigned int hxa_util_array_export_type_sizes[HXA_UAET_COUNT] = {sizeof(char), sizeof(unsigned char), sizeof(short), sizeof(unsigned short), sizeof(int), sizeof(unsigned int), sizeof(short), sizeof(float), sizeof(double)};\n"); 80 | for(i = 0; i < 3; i++) 81 | { 82 | for(j = 0; j < HXA_LDT_COUNT; j++) 83 | { 84 | for(k = 0; k < HXA_UAET_COUNT; k++) 85 | { 86 | switch(i) 87 | { 88 | case 0 : 89 | fprintf(f, "void hxa_type_convert_vertex_%s_to_%s(unsigned char *write, unsigned char *read, unsigned int write_stride, unsigned int read_stride, unsigned int component_count, unsigned int vertex_length)\n", export_type_names[layer_data_types[j]], export_type_names[k]); 90 | break; 91 | case 1 : 92 | fprintf(f, "void hxa_type_convert_reference_%s_to_%s(unsigned char *write, unsigned char *read, unsigned int write_stride, unsigned int read_stride, unsigned int component_count, int *reference, unsigned int ref_length)\n", export_type_names[layer_data_types[j]], export_type_names[k]); 93 | break; 94 | case 2 : 95 | fprintf(f, "void hxa_type_convert_face_%s_to_%s(unsigned char *write, unsigned char *read, unsigned int write_stride, unsigned int read_stride, unsigned int component_count, int *reference, unsigned int ref_length)\n", export_type_names[layer_data_types[j]], export_type_names[k]); 96 | break; 97 | } 98 | fprintf(f, "{\n"); 99 | fprintf(f, "\t%s *read_type;\n", export_type_strings[layer_data_types[j]]); 100 | fprintf(f, "\t%s *write_type;\n", export_type_strings[k]); 101 | if(k < HXA_UAET_HALF16) 102 | fprintf(f, "\tsigned long long tmp;\n"); 103 | fprintf(f, "\tunsigned int i, j, k;\n"); 104 | switch(i) 105 | { 106 | case 0 : 107 | fprintf(f, "\tfor(i = 0; i < vertex_length; i++)\n\t{\n"); 108 | fprintf(f, "\t\tread_type = &read[i * read_stride];\n"); 109 | break; 110 | case 1 : 111 | fprintf(f, "\tfor(i = 0; i < ref_length; i++)\n\t{\n"); 112 | fprintf(f, "\t\tread_type = &read[hxa_ref(reference, i) * read_stride];\n"); 113 | break; 114 | case 2 : 115 | fprintf(f, "\tfor(i = k = 0; i < ref_length; i++)\n\t{\n"); 116 | fprintf(f, "\t\tread_type = &read[k * read_stride];\n"); 117 | fprintf(f, "\t\tif(reference[i] < 0)\n"); 118 | fprintf(f, "\t\t\tk++;\n"); 119 | break; 120 | } 121 | fprintf(f, "\t\twrite_type = &write[i * write_stride];\n"); 122 | if(layer_data_types[j] == k) 123 | { 124 | fprintf(f, "\t\tmemcpy(write_type, read_type, sizeof(%s) * component_count);\n", export_type_strings[layer_data_types[j]]); 125 | }else 126 | { 127 | fprintf(f, "\t\tfor(j = 0; j < component_count; j++)\n"); 128 | if(k == HXA_UAET_HALF16) 129 | fprintf(f, "\t\t\twrite_type[j] = hxa_float32_to_float16((float)read_type[j]);\n"); 130 | else if(k > HXA_UAET_HALF16) 131 | fprintf(f, "\t\t\twrite_type[j] = (%s)read_type[j];\n", export_type_strings[k]); 132 | else 133 | { 134 | fprintf(f, "\t\t{\n"); 135 | if(layer_data_types[j] > HXA_UAET_HALF16) 136 | fprintf(f, "\t\t\ttmp = (signed long long)(read_type[j] * %u.0);\n", export_type_scale[k]); 137 | else 138 | fprintf(f, "\t\t\ttmp = (signed long long)read_type[j];\n"); 139 | 140 | if(export_type_min[k] > export_type_min[layer_data_types[j]]) 141 | { 142 | fprintf(f, "\t\t\tif(tmp < %lli)\n", export_type_min[k]); 143 | fprintf(f, "\t\t\t\ttmp = %lli;\n", export_type_min[k]); 144 | } 145 | if(export_type_max[k] < export_type_max[layer_data_types[j]]) 146 | { 147 | fprintf(f, "\t\t\tif(tmp > %lli)\n", export_type_max[k]); 148 | fprintf(f, "\t\t\t\ttmp = %lli;\n", export_type_max[k]); 149 | } 150 | fprintf(f, "\t\t\twrite_type[j] = (%s)tmp;\n", export_type_strings[k]); 151 | fprintf(f, "\t\t}\n"); 152 | } 153 | } 154 | fprintf(f, "\t}\n"); 155 | fprintf(f, "}\n\n\n"); 156 | } 157 | } 158 | } 159 | for(i = 0; i < 2; i++) 160 | { 161 | if(i == 0) 162 | fprintf(f, "unsigned char *hxa_type_vertex_convert(HXANode *node, unsigned char *buffer, unsigned int param_count, char **param_names, HxAUtilArrayExportTypes *param_types, unsigned int *param_dimentions)\n"); 163 | else 164 | fprintf(f, "unsigned char *hxa_type_reference_convert(HXANode *node, unsigned char *buffer, unsigned int param_count, char **param_names, HxAUtilArrayExportTypes *param_types, unsigned int *param_dimentions)\n"); 165 | fprintf(f, "{\n"); 166 | fprintf(f, "\tunsigned int i, j, k, stride, offset;\n"); 167 | fprintf(f, "\tfor(i = stride = 0; i < param_count; i++)\n"); 168 | fprintf(f, "\t\tstride += param_dimentions[i] * hxa_util_array_export_type_sizes[param_types[i]];\n"); 169 | fprintf(f, "\tif(buffer == NULL)\n"); 170 | if(i == 0) 171 | fprintf(f, "\t\tbuffer = malloc(stride * node->content.geometry.vertex_count);\n"); 172 | else 173 | fprintf(f, "\t\tbuffer = malloc(stride * node->content.geometry.edge_corner_count);\n"); 174 | for(l = 0; l < 3 && (i != 0 || l < 1); l++) 175 | { 176 | fprintf(f, "\tfor(i = offset = 0; i < param_count; i++)\n"); 177 | fprintf(f, "\t{\n"); 178 | fprintf(f, "\t\tfor(j = 0; j < node->content.geometry.%s.layer_count; j++)\n", stack_names[l]); 179 | fprintf(f, "\t\t{\n"); 180 | fprintf(f, "\t\t\tfor(k = 0; 0 != node->content.geometry.%s.layers[j].name[k] && node->content.geometry.%s.layers[j].name[k] == param_names[i][k]; k++);\n", stack_names[l], stack_names[l]); 181 | fprintf(f, "\t\t\tif(node->content.geometry.%s.layers[j].name[k] == param_names[i][k])\n", stack_names[l]); 182 | fprintf(f, "\t\t\t{\n"); 183 | fprintf(f, "\t\t\t\tswitch(node->content.geometry.%s.layers[j].type)\n", stack_names[l]); 184 | fprintf(f, "\t\t\t\t{\n"); 185 | for(j = 0; j < HXA_LDT_COUNT; j++) 186 | { 187 | fprintf(f, "\t\t\t\t\tcase %u :\n", j); 188 | fprintf(f, "\t\t\t\t\t\tswitch(param_types[i])\n"); 189 | fprintf(f, "\t\t\t\t\t\t{\n"); 190 | for(k = 0; k < HXA_UAET_COUNT; k++) 191 | { 192 | HXANode *node; 193 | 194 | fprintf(f, "\t\t\t\t\t\t\tcase %u :\n", k); 195 | if(i == 0) 196 | { 197 | fprintf(f, "\t\t\t\t\t\t\t\thxa_type_convert_vertex_%s_to_%s(&buffer[offset],\n", export_type_names[layer_data_types[j]], export_type_names[k]); 198 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.%s.layers[j].data.%s,\n", stack_names[l], export_type_enum_names[j]); 199 | fprintf(f, "\t\t\t\t\t\t\t\t\tstride,\n"); 200 | fprintf(f, "\t\t\t\t\t\t\t\t\tsizeof(%s) * node->content.geometry.%s.layers[j].components,\n", export_type_strings[layer_data_types[j]], stack_names[l]); 201 | fprintf(f, "\t\t\t\t\t\t\t\t\tparam_dimentions[i],\n"); 202 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.vertex_count);\n"); 203 | }else 204 | { 205 | switch(l) 206 | { 207 | case 0 : 208 | fprintf(f, "\t\t\t\t\t\t\t\thxa_type_convert_reference_%s_to_%s(&buffer[offset],\n", export_type_names[layer_data_types[j]], export_type_names[k]); 209 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.%s.layers[j].data.%s,\n", stack_names[l], export_type_enum_names[j]); 210 | fprintf(f, "\t\t\t\t\t\t\t\t\tstride,\n"); 211 | fprintf(f, "\t\t\t\t\t\t\t\t\tsizeof(%s) * node->content.geometry.%s.layers[j].components,\n", export_type_strings[layer_data_types[j]], stack_names[l]); 212 | fprintf(f, "\t\t\t\t\t\t\t\t\tparam_dimentions[i],\n"); 213 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.corner_stack.layers->data.int32_data,\n", export_type_names[layer_data_types[j]]); 214 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.edge_corner_count);\n"); 215 | break; 216 | case 1 : 217 | fprintf(f, "\t\t\t\t\t\t\t\thxa_type_convert_vertex_%s_to_%s(&buffer[offset],\n", export_type_names[layer_data_types[j]], export_type_names[k]); 218 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.%s.layers[j].data.%s,\n", stack_names[l], export_type_enum_names[j]); 219 | fprintf(f, "\t\t\t\t\t\t\t\t\tstride,\n"); 220 | fprintf(f, "\t\t\t\t\t\t\t\t\tsizeof(%s) * node->content.geometry.%s.layers[j].components,\n", export_type_strings[layer_data_types[j]], stack_names[l]); 221 | fprintf(f, "\t\t\t\t\t\t\t\t\tparam_dimentions[i],\n"); 222 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.edge_corner_count);\n"); 223 | break; 224 | case 2 : 225 | fprintf(f, "\t\t\t\t\t\t\t\thxa_type_convert_face_%s_to_%s(&buffer[offset],\n", export_type_names[layer_data_types[j]], export_type_names[k]); 226 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.%s.layers[j].data.%s,\n", stack_names[l], export_type_enum_names[j]); 227 | fprintf(f, "\t\t\t\t\t\t\t\t\tstride,\n"); 228 | fprintf(f, "\t\t\t\t\t\t\t\t\tsizeof(%s) * node->content.geometry.%s.layers[j].components,\n", export_type_strings[layer_data_types[j]], stack_names[l]); 229 | fprintf(f, "\t\t\t\t\t\t\t\t\tparam_dimentions[i],\n"); 230 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.corner_stack.layers->data.int32_data,\n", export_type_names[layer_data_types[j]]); 231 | fprintf(f, "\t\t\t\t\t\t\t\t\tnode->content.geometry.edge_corner_count);\n"); 232 | break; 233 | } 234 | } 235 | fprintf(f, "\t\t\t\t\t\t\tbreak;\n"); 236 | } 237 | fprintf(f, "\t\t\t\t\t\t}\n"); 238 | fprintf(f, "\t\t\t\t\tbreak;\n"); 239 | } 240 | fprintf(f, "\t\t\t\t}\n"); 241 | fprintf(f, "\t\t\t}\n"); 242 | fprintf(f, "\t\t}\n"); 243 | fprintf(f, "\t\toffset += param_dimentions[i] * hxa_util_array_export_type_sizes[param_types[i]];\n"); 244 | fprintf(f, "\t}\n"); 245 | } 246 | fprintf(f, "\treturn buffer;\n"); 247 | fprintf(f, "}\n"); 248 | } 249 | fclose(f); 250 | exit(0); 251 | } 252 | 253 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## HxA 3D asset format 2 | --------------------- 3 | 4 | HxA is a interchangeable graphics asset format. Written by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com 5 | 6 | # Rationale 7 | ----------- 8 | 9 | - Does the world need another Graphics file format? 10 | 11 | Unfortunately, Yes. All existing formats are either too large and complicated to be implemented from scratch, or don't have some basic features needed in modern computer graphics. 12 | 13 | - Who is this format for? 14 | 15 | For people who want a capable open Graphics format that can be implemented from scratch in a few hours. It is ideal for graphics researchers, game developers or other people who wants to build custom graphics pipelines. Given how easy it is to parse and write, it should be easy to write utilities that process assets to preform tasks like: generating normals, lightmaps, tangent spaces, Error detection, GPU optimization, LOD generation, and UV mapping. 16 | 17 | - Why store images in the format when there are so many good image formats already? 18 | 19 | Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely on 1D, 3D, CUBE, Multilayer, multi channel, floating point bitmap buffers. There almost no formats for this kind of data. Also 3D files that reference separate image files rely on file paths, and this often creates issues when the assets are moved. By including the texture data in the files directly the assets become self contained. 20 | 21 | - Why doesn't the format support ? 22 | 23 | The entire point of HxA is to make a format that is practical to implement. Features like NURBSs, Construction history, or BSP trees would make the format too large to serve its purpose. The facilities of the formats to store meta data should make the format flexible enough for most uses. Adding HxA support should be something anyone can do in a days work. 24 | 25 | # Structure 26 | ------------ 27 | 28 | HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has a few basic structures, and depending on how they are used they mean different things. This means that you can implement a tool that loads the entire file, modifies the parts it cares about and leaves the rest intact. It is also possible to write a tool that makes all data in the file editable without the need to understand its use. It is also possible for anyone to use the format to store data axillary data. Anyone who wants to store data not covered by a convention can submit a convention to extend the format. There should never be a convention for storing the same data in two differed ways. 29 | 30 | The data is stored in a number of nodes themselves stored in an array. Each node stores an array of meta data. Meta data can describe anything you want, and a lot of conventions will use meta data to store additional information, for things like transforms, lights, shaders and animation. 31 | Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists of a number of named layers. All layers in the stack have the same number of elements. Each layer describes one property of the primitive. Each layer can have multiple channels and each layer can store data of a different type. 32 | 33 | HaX stores 3 kinds of nodes: 34 | 35 | - Pixel data. 36 | - Polygon geometry data. 37 | - Meta data only. 38 | 39 | Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness, Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the layers to store things like color. The length of the layer stack is determined by the type and dimensions stored in the array. 40 | 41 | Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The vertex data stores things like vertices, blend shapes, weight maps, and vertex colors. The first layer in a vertex stack has to be a 3 channel layer named "position" describing the base position of the vertices. The corner stack describes data per corner or edge of the polygons. It can be used for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel integer layer named "index" describing the vertices used to form polygons. The last value in each polygon has a negative index to indicate the end of the polygon. 42 | 43 | Example: 44 | 45 | A quad and a tri with the vertex index: 46 | ``` 47 | [0, 1, 2, 3] [1, 4, 2] 48 | ``` 49 | is stored: 50 | ``` 51 | [0, 1, 2, -4, 1, 4, -3] 52 | ``` 53 | 54 | The face stack stores values per face. the length of the face stack has to match the number of negative values in the index layer in the corner stack. The face stack can be used to store things like material index. 55 | 56 | # Storage 57 | --------- 58 | 59 | All data is stored in little endian byte order with no padding. The layout mirrors the structs defined below with a few exceptions. 60 | All names are stored as a 8bit unsigned integer indicating the length of the name followed by that many characters. Termination is not stored in the file. 61 | Text strings stored in meta data are stored the same way as names, but instead of a 8bit unsigned integer a 32bit unsigned integer is used. 62 | 63 | ```c 64 | #ifndef HAX_INCLUDE 65 | #define HAX_INCLUDE 66 | 67 | #define HXA_VERSION_API "0.3" 68 | #define HXA_VERSION_FORMAT 3 69 | 70 | typedef unsigned char hxa_uint8; 71 | typedef signed int hxa_int32; 72 | typedef unsigned int hxa_uint32; 73 | typedef signed long long hxa_int64; 74 | typedef unsigned long long hxa_uint64; 75 | 76 | /* 77 | HaX stores 3 types of nodes: 78 | */ 79 | 80 | typedef enum{ 81 | HXA_NT_META_ONLY = 0, // node only containing meta data. 82 | HXA_NT_GEOMETRY = 1, // node containing a geometry mesh, and meta data. 83 | HXA_NT_IMAGE = 2, // node containing a 1D, 2D, 3D, or Cube image, and meta data. 84 | HXA_NT_COUNT = 3 // the number of different nodes that can be stored in the file. 85 | }HXANodeType; 86 | 87 | /* 88 | HaX stores layer data in the following types: 89 | */ 90 | typedef enum{ 91 | HXA_LDT_UINT8 = 0, /* 8bit unsigned integer, */ 92 | HXA_LDT_INT32 = 1, /* 32bit signed integer */ 93 | HXA_LDT_FLOAT = 2, /* 32bit IEEE 754 floating point value */ 94 | HXA_LDT_DOUBLE = 3, /* 64bit IEEE 754 floating point value */ 95 | HXA_LDT_COUNT = 4 /* number of types supported by layers */ 96 | }HXALayerDataType; 97 | /* 98 | Pixel data is arranged in the following configurations 99 | */ 100 | typedef enum{ 101 | HXA_IT_CUBE_IMAGE = 0, /* 6 sided qube, in the order of: +x, -x, +y, -y, +z, -z. */ 102 | HXA_IT_1D_IMAGE = 1, /* One dimentional pixel data. */ 103 | HXA_IT_2D_IMAGE = 2, /* Two dimentional pixel data. */ 104 | HXA_IT_3D_IMAGE = 3, /* Three dimentional pixel data. */ 105 | }HXAImageType; 106 | 107 | typedef enum{ 108 | HXA_MDT_INT64 = 0, 109 | HXA_MDT_DOUBLE = 1, 110 | HXA_MDT_NODE = 2, 111 | HXA_MDT_TEXT = 3, 112 | HXA_MDT_BINARY = 4, 113 | HXA_MDT_META = 5, 114 | HXA_MDT_COUNT = 6 115 | }HXAMetaDataType; 116 | 117 | #define HXA_NAME_MAX_LENGTH 256 // 118 | 119 | typedef struct{ 120 | char name[HXA_NAME_MAX_LENGTH]; // name of the meta data value. 121 | HXAMetaDataType type; // type of value. Stored in the file as a uint8. 122 | hxa_uint32 array_length; // how many values are stored / the length of the stored text string (excluding termination) 123 | union{ 124 | hxa_uint64 *int64_value; // integer values 125 | double *double_value; // double values 126 | hxa_uint32 *node_value; // a reference to another node 127 | char *text_value; // text string 128 | unsigned char *bin_value; // binary data string 129 | void *array_of_meta; // Meta structures 130 | }value; 131 | }HXAMeta; /* meta data key/value store */ 132 | 133 | 134 | /* Layers are arrays of data used to store geometry and pixel data */ 135 | 136 | typedef struct{ 137 | char name[HXA_NAME_MAX_LENGTH]; // name of the layer. List of predefined names for common usages like uv, reference, blendshapes, weights ... 138 | hxa_uint8 components; // 2 for uv, 3 for xyz or rgb, 4 for rgba; 139 | HXALayerDataType type; // Stored in the file as a uint8. 140 | union{ 141 | hxa_uint8 *uint8_data; 142 | hxa_int32 *int32_data; 143 | float *float_data; 144 | double *double_data; 145 | }data; 146 | }HXALayer; 147 | 148 | /* Layers stacks are arrays of layers where all the layers have the same number of entries (polygons, edges, vertices or pixels) */ 149 | 150 | typedef struct{ 151 | hxa_uint32 layer_count; /* the number of loayers in a stack. */ 152 | HXALayer *layers; /* An array of layers. */ 153 | }HXALayerStack; 154 | 155 | /* A file consists of an array of nodes, All noides have meta data. Geometry nodes have geometry, image nodes have pixels*/ 156 | 157 | typedef struct{ 158 | HXANodeType type; // what type of node is this? Stored in the file as a uint8. 159 | hxa_uint32 meta_data_count; // how many meta data key/values are stored in the node 160 | HXAMeta *meta_data; // array of key/values 161 | union{ 162 | struct{ 163 | hxa_uint32 vertex_count; // number of vertices 164 | HXALayerStack vertex_stack; // stack of vertex arrays. the first layer is always the vertex positions 165 | hxa_uint32 edge_corner_count; // number of corners 166 | HXALayerStack corner_stack; // stack of corner arrays, the first layer is allways a reference array (see below) 167 | HXALayerStack edge_stack; // stack of edge arrays 168 | hxa_uint32 face_count; // number of polygons 169 | HXALayerStack face_stack; // stack of per polygon data. 170 | }geometry; 171 | struct{ 172 | HXAImageType type; // type of image 173 | hxa_uint32 resolution[3]; // resolytion i X, Y and Z dimention; 174 | HXALayerStack image_stack; // the number of values in the stack is equal to the number of pixels depending on resolution 175 | }image; 176 | }content; 177 | }HXANode; 178 | 179 | #define HAX_MAGIC_NUMBER (*(hxa_uint32)"HaX") // 4290632 180 | 181 | typedef struct{ 182 | // hxa_uint32 magic_number; The file begins with a file identifyer. it always has to be the 4 bytes "HxA", See definition of HAX_MAGIC_NUMBER. Since the magic number is always the same we dont store it in this structure even if it is always precent in files. 183 | hxa_uint8 version; 184 | hxa_uint32 node_count; // number of nodes in the file 185 | HXANode *node_array; // array of nodes. 186 | }HXAFile; 187 | ``` 188 | 189 | # Conventions 190 | ------------- 191 | Much of HxA's use is based on convention. HxA lets users store aritrary data in its structure that can be parsed but whos semantic meaning does not need to be understood. 192 | 193 | A few conventions are hard, and some are soft. Hard convention that a user HAS to follow in order to produce a valid file. Hard conventions simplify parsing becaus the parser can make some assumptions. Soft convenbtions are basicly recomendations of how to store common data. 194 | 195 | If you use HxA for something not coverd by the conventiosns but need a convention for your usecase. Please let us know so that we can add it! 196 | 197 | 198 | ```c 199 | /* Hard conventions */ 200 | /* ---------------- */ 201 | 202 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME "vertex" 203 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_ID 0 204 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS 3 205 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME "reference" 206 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID 0 207 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS 1 208 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE HXA_LDT_INT32 209 | #define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME "neighbour" 210 | #define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE HXA_LDT_INT32 211 | 212 | /* Soft Conventions */ 213 | /* ---------------- */ 214 | 215 | /* geometry layers */ 216 | 217 | #define HXA_CONVENTION_SOFT_LAYER_SEQUENCE0 "sequence" 218 | #define HXA_CONVENTION_SOFT_LAYER_NAME_UV0 "uv" 219 | #define HXA_CONVENTION_SOFT_LAYER_NORMALS "normal" 220 | #define HXA_CONVENTION_SOFT_LAYER_TANGENT "tangent" 221 | #define HXA_CONVENTION_SOFT_LAYER_CREASES "creases" 222 | #define HXA_CONVENTION_SOFT_LAYER_SELECTION "selection" 223 | #define HXA_CONVENTION_SOFT_LAYER_SKIN_WEIGHT "skining_weight" 224 | #define HXA_CONVENTION_SOFT_LAYER_SKIN_REFERENCE "skining_reference" 225 | #define HXA_CONVENTION_SOFT_LAYER_SKIN_REFERENCE "skining_reference" 226 | #define HXA_CONVENTION_SOFT_LAYER_BLENDSHAPE "blendshape" 227 | #define HXA_CONVENTION_SOFT_LAYER_ADD_BLENDSHAPE "addblendshape" 228 | #define HXA_CONVENTION_SOFT_LAYER_MATERIAL_ID "material" 229 | 230 | /* Image layers */ 231 | 232 | #define HXA_CONVENTION_SOFT_ALBEDO "albedo" 233 | #define HXA_CONVENTION_SOFT_LIGHT "light" 234 | #define HXA_CONVENTION_SOFT_DISPLACEMENT "displacement" 235 | #define HXA_CONVENTION_SOFT_DISTORTION "distortion" 236 | #define HXA_CONVENTION_SOFT_AMBIENT_OCCLUSION "ambient_occlusion" 237 | 238 | /* tags layers */ 239 | 240 | #define HXA_CONVENTION_SOFT_NAME "name" 241 | #define HXA_CONVENTION_SOFT_TRANSFORM "transform" 242 | ``` 243 | -------------------------------------------------------------------------------- /hxa.h: -------------------------------------------------------------------------------- 1 | /* ------------- HxA 3D asset format --------------- 2 | HxA is a interchangeable graphics asset format. Written by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com 3 | 4 | Rational: 5 | --------- 6 | 7 | -Does the world need another Graphics file format? 8 | 9 | Unfortunately, Yes. All existing formats are either too large and complicated to be implemented from scratch, or don't have some basic features needed in modern computer graphics. 10 | 11 | -Who is this format for? 12 | 13 | For people who want a capable open Graphics format that can be implemented from scratch in a few hours. It is ideal for graphics researchers, game developers or other people who wants to build custom graphics pipelines. Given how easy it is to parse and write, it should be easy to write utilities that process assets to preform tasks like: generating normals, lightmaps, tangent spaces, Error detection, GPU optimization, LOD generation, and UV mapping. 14 | 15 | -Why store images in the format when there are so many good image formats already? 16 | 17 | Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely on 1D, 3D, CUBE, Multilayer, multi channel, floating point bitmap buffers. There almost no formats for this kind of data. Also 3D files that reference separate image files rely on file paths, and this often creates issues when the assets are moved. By including the texture data in the files directly the assets become self contained. 18 | 19 | -Why doesn't the format support ? 20 | 21 | Because the entire point is to make a format that can be implemented. Features like NURBSs, Construction history, or BSP trees would make the format too large to serve its purpose. The facilities of the formats to store meta data should make the format flexible enough for most uses. Adding HxA support should be something anyone can do in a days work. 22 | 23 | Structure: 24 | ---------- 25 | 26 | HxA is designed to be extremely simple to parse, and is therefor based around conventions. It has a few basic structures, and depending on how they are used they mean different things. This means that you can implement a tool that loads the entire file, modifies the parts it cares about and leaves the rest intact. It is also possible to write a tool that makes all data in the file editable without the need to understand its use. It is also possible for anyone to use the format to store data axillary data. Anyone who wants to store data not covered by a convention can submit a convention to extend the format. There should never be a convention for storing the same data in two differed ways. 27 | 28 | The data is story in a number of nodes that are stored in an array. Each node stores an array of meta data. Meta data can describe anything you want, and a lot of conventions will use meta data to store additional information, for things like transforms, lights, shaders and animation. 29 | Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists of a number of named layers. All layers in the stack have the same number of elements. Each layer describes one property of the primitive. Each layer can have multiple channels and each layer can store data of a different type. 30 | 31 | HaX stores 3 kinds of nodes 32 | -Pixel data. 33 | -Polygon geometry data. 34 | -Meta data only. 35 | 36 | Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness, Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the layers to store things like color. The length of the layer stack is determined by the type and dimensions stored in the 37 | 38 | Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The vertex data stores things like veritices, blend shapes, weight maps, and vertex colors. The first layer in a vertex stack has to be a 3 channel layer named "position" describing the base position of the vertices. The corner stack describes data per corner or edge of the polygons. It can be used for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel integer layer named "index" describing the vertices used to form polygons. The last value in each polygon has a negative - 1 index to indicate the end of the polygon. 39 | 40 | Example: 41 | A quad and a tri with the vertex index: 42 | [0, 1, 2, 3] [1, 4, 2] 43 | is stored: 44 | [0, 1, 2, -4, 1, 4, -3] 45 | 46 | The face stack stores values per face. the length of the face stack has to match the number of negative values in the index layer in the corner stack. The face stack can be used to store things like material index. 47 | 48 | Storage 49 | ------- 50 | 51 | All data is stored in little endian byte order with no padding. The layout mirrors the structs defined below with a few exceptions. 52 | All names are stored as a 8bit unsigned integer indicating the length of the name followed by that many characters. Termination is not stored in the file. 53 | Text strings stored in meta data are stored the same way as names, but instead of a 8bit unsigned integer a 32bit unsigned integer is used. 54 | 55 | */ 56 | 57 | #ifndef HAX_INCLUDE 58 | #define HAX_INCLUDE 59 | 60 | #define HXA_VERSION_API "0.3" 61 | #define HXA_VERSION_FORMAT 3 62 | 63 | typedef unsigned char hxa_uint8; 64 | typedef signed int hxa_int32; 65 | typedef unsigned int hxa_uint32; 66 | typedef signed long long hxa_int64; 67 | typedef unsigned long long hxa_uint64; 68 | 69 | #define HXA_NAME_MAX_LENGTH 256 // 70 | /* 71 | HaX stores 3 types of nodes: 72 | */ 73 | 74 | typedef enum{ 75 | HXA_NT_META_ONLY = 0, // node only containing meta data. 76 | HXA_NT_GEOMETRY = 1, // node containing a geometry mesh, and meta data. 77 | HXA_NT_IMAGE = 2, // node containing a 1D, 2D, 3D, or Cube image, and meta data. 78 | HXA_NT_COUNT = 3 // the number of different nodes that can be stored in the file. 79 | }HXANodeType; 80 | 81 | /* 82 | Pixel data is arranged in the following configurations 83 | */ 84 | typedef enum{ 85 | HXA_IT_CUBE_IMAGE = 0, /* 6 sided qube, in the order of: +x, -x, +y, -y, +z, -z. */ 86 | HXA_IT_1D_IMAGE = 1, /* One dimentional pixel data. */ 87 | HXA_IT_2D_IMAGE = 2, /* Two dimentional pixel data. */ 88 | HXA_IT_3D_IMAGE = 3, /* Three dimentional pixel data. */ 89 | }HXAImageType; 90 | 91 | typedef enum{ 92 | HXA_MDT_INT64 = 0, 93 | HXA_MDT_DOUBLE = 1, 94 | HXA_MDT_NODE = 2, 95 | HXA_MDT_TEXT = 3, 96 | HXA_MDT_BINARY = 4, 97 | HXA_MDT_META = 5, 98 | HXA_MDT_COUNT = 6 99 | }HXAMetaDataType; 100 | 101 | typedef struct{ 102 | char name[HXA_NAME_MAX_LENGTH]; // name of the meta data value. 103 | HXAMetaDataType type; // type of value. Stored in the file as a uint8. 104 | hxa_uint32 array_length; // how many values are stored / the length of the stored text string (excluding termination) 105 | union{ 106 | hxa_uint64 *int64_value; // integer values 107 | double *double_value; // double values 108 | hxa_uint32 *node_value; // a reference to another node 109 | char *text_value; // text string 110 | unsigned char *bin_value; // binary data string 111 | void *array_of_meta; // Meta structures 112 | }value; 113 | }HXAMeta; /* meta data key/value store */ 114 | 115 | 116 | /* 117 | HaX stores layer data in the following types: 118 | */ 119 | typedef enum{ 120 | HXA_LDT_UINT8 = 0, /* 8bit unsigned integer, */ 121 | HXA_LDT_INT32 = 1, /* 32bit signed integer */ 122 | HXA_LDT_FLOAT = 2, /* 32bit IEEE 754 floating point value */ 123 | HXA_LDT_DOUBLE = 3, /* 64bit IEEE 754 floating point value */ 124 | HXA_LDT_COUNT = 4 /* number of types supported by layers */ 125 | }HXALayerDataType; 126 | 127 | /* Layers are arrays of data used to store geometry and pixel data */ 128 | 129 | typedef struct{ 130 | char name[HXA_NAME_MAX_LENGTH]; // name of the layer. List of predefined names for common usages like uv, reference, blendshapes, weights ... 131 | hxa_uint8 components; // 2 for uv, 3 for xyz or rgb, 4 for rgba. from 1 - 255 is legal. 132 | HXALayerDataType type; // Stored in the file as a uint8. 133 | union{ 134 | hxa_uint8 *uint8_data; 135 | hxa_int32 *int32_data; 136 | float *float_data; 137 | double *double_data; 138 | }data; 139 | }HXALayer; 140 | 141 | /* Layers stacks are arrays of layers where all the layers have the same number of entries (polygons, edges, vertices or pixels) */ 142 | /* 143 | { 144 | vertex_layer_stack.layers[0].name = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME; 145 | vertex_layer_stack.layers[0].data.float_data = {0, 0, 0, 1, 1, 1}; 146 | vertex_layer_stack.layers[0].components = 3; 147 | 148 | corner_layer_stack.layers[0].name = HXA_CONVENTION_HARD_BASE_REFERECNE_LAYER_NAME; 149 | corner_layer_stack.layers[0].data.int32_data = {0, 1, -3}; 150 | corner_layer_stack.layers[0].components = 1; 151 | corner_layer_stack.layers[1].name = "UV"; 152 | corner_layer_stack.layers[1].data.double_data = {1, 1, 0, 0, 1, 0}; 153 | corner_layer_stack.layers[1].components = 2; 154 | } 155 | { 156 | HXANode *node; 157 | node = hxa_util_load("file.hxa", TRUE); 158 | hxa_util_triangulate_node(node, 3); 159 | node.... 160 | }*/ 161 | 162 | 163 | 164 | typedef struct{ 165 | hxa_uint32 layer_count; /* the number of loayers in a stack. */ 166 | HXALayer *layers; /* An array of layers. */ 167 | }HXALayerStack; 168 | 169 | /* A file consists of an array of nodes, All noides have meta data. Geometry nodes have geometry, image nodes have pixels*/ 170 | 171 | typedef struct{ 172 | HXANodeType type; // what type of node is this? Stored in the file as a uint8. 173 | hxa_uint32 meta_data_count; // how many meta data key/values are stored in the node 174 | HXAMeta *meta_data; // array of key/values 175 | union{ 176 | struct{ 177 | hxa_uint32 vertex_count; // number of vertices 178 | HXALayerStack vertex_stack; // stack of vertex arrays. the first layer is always the vertex positions 179 | hxa_uint32 edge_corner_count; // number of corners 180 | HXALayerStack corner_stack; // stack of corner arrays, the first layer is allways a reference array (see below) 181 | HXALayerStack edge_stack; // stack of edge arrays 182 | hxa_uint32 face_count; // number of polygons 183 | HXALayerStack face_stack; // stack of per polygon data. 184 | }geometry; 185 | struct{ 186 | HXAImageType type; // type of image 187 | hxa_uint32 resolution[3]; // resolytion i X, Y and Z dimention; 188 | HXALayerStack image_stack; // the number of values in the stack is equal to the number of pixels depending on resolution 189 | }image; 190 | }content; 191 | }HXANode; 192 | 193 | #define HAX_MAGIC_NUMBER (*(hxa_uint32)"HaX") // 4290632 194 | 195 | typedef struct{ 196 | // hxa_uint32 magic_number; The file begins with a file identifyer. it always has to be the 4 bytes "HxA", See definition of HAX_MAGIC_NUMBER. Since the magic number is always the same we dont store it in this structure even if it is always precent in files. 197 | hxa_uint8 version; // HXA_VERSION_FORMAT 198 | hxa_uint32 node_count; // number of nodes in the file 199 | HXANode *node_array; // array of nodes. 200 | }HXAFile; 201 | 202 | /* Conventions */ 203 | /* ------------ 204 | Much of HxA's use is based on convention. HxA lets users store aritrary data in its structure that can be parsed but whos semantic meaning does not need to be understood. 205 | 206 | A few conventions are hard, and some are soft. Hard convention that a user HAS to follow in order to produce a valid file. Hard conventions simplify parsing becaus the parser can make some assumptions. Soft convenbtions are basicly recomendations of how to store common data. 207 | 208 | If you use HxA for something not coverd by the conventiosns but need a convention for your usecase. Please let us know so that we can add it! 209 | */ 210 | 211 | /* Hard conventions */ 212 | /* ---------------- */ 213 | 214 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME "vertex" 215 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_ID 0 216 | #define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS 3 217 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME "reference" 218 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID 0 219 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS 1 220 | #define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE HXA_LDT_INT32 221 | #define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME "neighbour" 222 | #define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE HXA_LDT_INT32 223 | 224 | /* Soft Conventions */ 225 | /* ---------------- */ 226 | 227 | /* geometry layers */ 228 | 229 | #define HXA_CONVENTION_SOFT_LAYER_SEQUENCE0 "sequence" 230 | #define HXA_CONVENTION_SOFT_LAYER_UV0 "uv" 231 | #define HXA_CONVENTION_SOFT_LAYER_NORMALS "normal" 232 | #define HXA_CONVENTION_SOFT_LAYER_BINORMAL "binormal" 233 | #define HXA_CONVENTION_SOFT_LAYER_TANGENT "tangent" 234 | #define HXA_CONVENTION_SOFT_LAYER_COLOR "color" 235 | #define HXA_CONVENTION_SOFT_LAYER_CREASES "creases" 236 | #define HXA_CONVENTION_SOFT_LAYER_SELECTION "select" 237 | #define HXA_CONVENTION_SOFT_LAYER_SKIN_WEIGHT "skining_weight" 238 | #define HXA_CONVENTION_SOFT_LAYER_SKIN_REFERENCE "skining_reference" 239 | #define HXA_CONVENTION_SOFT_LAYER_BLENDSHAPE "blendshape" 240 | #define HXA_CONVENTION_SOFT_LAYER_ADD_BLENDSHAPE "addblendshape" 241 | #define HXA_CONVENTION_SOFT_LAYER_MATERIAL_ID "material" 242 | #define HXA_CONVENTION_SOFT_LAYER_GROUP_ID "group" 243 | 244 | /* Image layers */ 245 | 246 | #define HXA_CONVENTION_SOFT_ALBEDO "albedo" 247 | #define HXA_CONVENTION_SOFT_LIGHT "light" 248 | #define HXA_CONVENTION_SOFT_DISPLACEMENT "displacement" 249 | #define HXA_CONVENTION_SOFT_DISTORTION "distortion" 250 | #define HXA_CONVENTION_SOFT_AMBIENT_OCCLUSION "ambient_occlusion" 251 | 252 | /* tags layers */ 253 | 254 | #define HXA_CONVENTION_SOFT_NAME "name" 255 | #define HXA_CONVENTION_SOFT_TRANSFORM "transform" 256 | 257 | 258 | #endif 259 | 260 | -------------------------------------------------------------------------------- /hxa_fbx_convert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hxa.h" 5 | #include "hxa_fbx_internal.h" 6 | 7 | 8 | FBXRecord *hxa_fbx_convert_record_find(FBXRecord *record, char *name, unsigned int start, unsigned int prefix) 9 | { 10 | FBXRecord *child; 11 | unsigned int i, j, k; 12 | for(i = k = 0; i < record->used; i++) 13 | { 14 | child = &((FBXRecord *)record->children)[i]; 15 | // if(prefix) 16 | // printf("child->name %s\n", child->name); 17 | for(j = 0; name[j] != 0 && name[j] == child->name[j]; j++); 18 | if(name[j] == 0 && (prefix || child->name[j] == 0)) 19 | { 20 | if(start == k++) 21 | return child; 22 | } 23 | } 24 | return NULL; 25 | } 26 | 27 | int hxa_fbx_convert_property_test(FBXRecord *record, char *property_name) 28 | { 29 | FBXProperty *p; 30 | uint i, j; 31 | for(i = 0; i < record->property_count; i++) 32 | { 33 | if(record->property[i].type == FBX_PROPERTY_TYPE_TEXT) 34 | { 35 | for(j = 0; property_name[j] != 0 && record->property[i].data.buffer->buffer.text[j] == property_name[j]; j++); 36 | if(property_name[j] == record->property[i].data.buffer->buffer.text[j]) 37 | return TRUE; 38 | } 39 | } 40 | return FALSE; 41 | } 42 | 43 | int hxa_fbx_convert_layer_read(FBXRecord *record, HXALayerStack *layer_stack, uint length) 44 | { 45 | char *index = "Index"; 46 | HXALayer *layer; 47 | FBXProperty *p, *index_property = NULL; 48 | FBXRecord *param; 49 | uint i, j, k, l, type_size, data_size, vertex_range, components; 50 | unsigned char *data = NULL, *temp_buff = NULL; 51 | size_t type_sizes[HXA_LDT_COUNT] = {sizeof(unsigned char), sizeof(int), sizeof(float), sizeof(double)}; 52 | unsigned int fbx_type_convesion[FBX_PROPERTY_TYPE_COUNT] = {HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_BOOLEAN, 53 | HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT8, 54 | HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT16, 55 | HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT32, 56 | HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT64, 57 | HXA_LDT_FLOAT, // FBX_PROPERTY_TYPE_FLOAT32, 58 | HXA_LDT_DOUBLE, // FBX_PROPERTY_TYPE_FLOAT64, 59 | HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_TEXT, 60 | HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_RAW, 61 | HXA_LDT_COUNT}; // FBX_PROPERTY_TYPE_UNKNOWN, 62 | 63 | 64 | 65 | param = hxa_fbx_convert_record_find(record, "ReferenceInformationType", 0, FALSE); 66 | 67 | if(param != NULL && (hxa_fbx_convert_property_test(param, "IndexToDirect") || hxa_fbx_convert_property_test(param, "Index"))) 68 | { 69 | printf("IndexToDirect/n"); 70 | for(i = 0; i < record->used && index_property == NULL; i++) 71 | { 72 | param = &((FBXRecord *)record->children)[i]; 73 | for(j = 0; j < param->property_count && index_property == NULL; j++) 74 | { 75 | if(param->property[j].array_length % length == 0) 76 | { 77 | if(param->property[j].type == FBX_PROPERTY_TYPE_INT8 || 78 | param->property[j].type == FBX_PROPERTY_TYPE_INT16 || 79 | param->property[j].type == FBX_PROPERTY_TYPE_INT32 || 80 | param->property[j].type == FBX_PROPERTY_TYPE_INT64) 81 | { 82 | for(k = 0; k < param->name[k] != 0; k++) 83 | { 84 | for(l = 0; index[l] != 0 && index[l] == param->name[k + l]; l++); 85 | if(index[l] != 0) 86 | { 87 | index_property = ¶m->property[j]; 88 | vertex_range = 0; 89 | if(index_property->type == FBX_PROPERTY_TYPE_INT8) 90 | for(k = 0; k < index_property->array_length; k++) 91 | if(vertex_range < ((char *)index_property->data.array)[k]) 92 | vertex_range = ((char *)index_property->data.array)[k]; 93 | if(index_property->type == FBX_PROPERTY_TYPE_INT16) 94 | for(k = 0; k < index_property->array_length; k++) 95 | if(vertex_range < ((short *)index_property->data.array)[k]) 96 | vertex_range = ((short *)index_property->data.array)[k]; 97 | if(index_property->type == FBX_PROPERTY_TYPE_INT32) 98 | for(k = 0; k < index_property->array_length; k++) 99 | if(vertex_range < ((int *)index_property->data.array)[k]) 100 | vertex_range = ((int *)index_property->data.array)[k]; 101 | if(index_property->type == FBX_PROPERTY_TYPE_INT64) 102 | for(k = 0; k < index_property->array_length; k++) 103 | if(vertex_range < ((long long *)index_property->data.array)[k]) 104 | vertex_range = ((long long *)index_property->data.array)[k]; 105 | vertex_range++; 106 | break; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | if(index_property == NULL) 114 | return FALSE; 115 | }else 116 | vertex_range = length; 117 | 118 | 119 | for(i = 0; data == NULL && i < record->used; i++) 120 | { 121 | param = &((FBXRecord *)record->children)[i]; 122 | for(j = 0; j < param->property_count; j++) 123 | { 124 | if(¶m->property[j] != index_property && 125 | param->property[j].array_length >= vertex_range && 126 | fbx_type_convesion[param->property[j].type] != HXA_LDT_COUNT) 127 | { 128 | 129 | data_size = param->property[j].array_length; 130 | data = param->property[j].data.array; 131 | ++layer_stack->layer_count; 132 | layer_stack->layers = realloc(layer_stack->layers, (sizeof *layer_stack->layers) * layer_stack->layer_count); 133 | layer = &layer_stack->layers[layer_stack->layer_count - 1]; 134 | for(k = 0; param->name[k] != 0; k++) 135 | layer->name[k] = param->name[k]; 136 | 137 | layer->name[k] = 0; 138 | if(layer->name[0] == 'U' && layer->name[1] == 'V') 139 | k = 0; 140 | layer->type = fbx_type_convesion[param->property[j].type]; 141 | type_size = type_sizes[layer->type]; 142 | if(index_property == NULL) 143 | layer->components = param->property[j].array_length / length; 144 | else 145 | layer->components = param->property[j].array_length / vertex_range; 146 | layer->data.uint8_data = malloc(type_size * length * layer->components); 147 | 148 | if(param->property[j].type == FBX_PROPERTY_TYPE_INT8) 149 | { 150 | temp_buff = malloc((sizeof *temp_buff) * data_size); 151 | for(k = 0; k < 0; k++) 152 | temp_buff[k] = (int)((char *)param->property[j].data.array)[k]; 153 | }else if(param->property[j].type == FBX_PROPERTY_TYPE_INT16) 154 | { 155 | temp_buff = malloc((sizeof *temp_buff) * data_size); 156 | for(k = 0; k < 0; k++) 157 | temp_buff[k] = (int)((short *)param->property[j].data.array)[k]; 158 | }else if(param->property[j].type == FBX_PROPERTY_TYPE_INT64) 159 | { 160 | temp_buff = malloc((sizeof *temp_buff) * data_size); 161 | for(k = 0; k < 0; k++) 162 | temp_buff[k] = (int)((long long *)param->property[j].data.array)[k]; 163 | } 164 | break; 165 | } 166 | } 167 | } 168 | if(data == NULL) 169 | return FALSE; 170 | 171 | 172 | if(index_property != NULL) 173 | { 174 | layer->data.uint8_data = malloc((sizeof *layer->data.uint8_data) * layer->components * length * type_size); 175 | if(index_property->type == FBX_PROPERTY_TYPE_INT8) 176 | for(k = 0; k < index_property->array_length; k++) 177 | memcpy(&layer->data.uint8_data[layer->components * k * type_size], &data[layer->components * (size_t)((char *)index_property->data.array)[k] * sizeof(char)], layer->components * type_size); 178 | if(index_property->type == FBX_PROPERTY_TYPE_INT16) 179 | for(k = 0; k < index_property->array_length; k++) 180 | memcpy(&layer->data.uint8_data[layer->components * k * type_size], &data[layer->components * (size_t)((short *)index_property->data.array)[k] * sizeof(short)], layer->components * type_size); 181 | if(index_property->type == FBX_PROPERTY_TYPE_INT32) 182 | for(k = 0; k < index_property->array_length; k++) 183 | memcpy(&layer->data.uint8_data[layer->components * k * type_size], &data[layer->components * (size_t)((int *)index_property->data.array)[k] * sizeof(int)], layer->components * type_size); 184 | if(index_property->type == FBX_PROPERTY_TYPE_INT64) 185 | for(k = 0; k < index_property->array_length; k++) 186 | memcpy(&layer->data.uint8_data[layer->components * k * type_size], &data[layer->components * (size_t)((long long *)index_property->data.array)[k] * sizeof(long long)], layer->components * type_size); 187 | }else 188 | memcpy(layer->data.uint8_data, data, type_size * length * layer->components); 189 | if(temp_buff != NULL) 190 | free(temp_buff); 191 | return FALSE; 192 | } 193 | 194 | extern void fbx_record_print_small(FBXRecord *record, uint generation); 195 | 196 | HXAFile *hxa_fbx_convert(FBXRecord *record, HXAFile *file) 197 | { 198 | FBXRecord *object, *geometry, *vertices, *polygonvertexindex, *layer, *param; 199 | HXALayerStack *stack; 200 | HXANode *node; 201 | unsigned int i, j, k, *ref, array_length; 202 | object = hxa_fbx_convert_record_find(record, "Objects", 0, FALSE); 203 | if(object == NULL) 204 | return NULL; 205 | if(file == NULL) 206 | { 207 | file = malloc(sizeof *file); 208 | file->version = HXA_VERSION_FORMAT; 209 | file->node_count = 0; 210 | file->node_array = NULL; 211 | } 212 | for(i = 0; (geometry = hxa_fbx_convert_record_find(object, "Geometry", i, FALSE)) != NULL; i++) 213 | { 214 | fbx_record_print(geometry, 1); 215 | vertices = hxa_fbx_convert_record_find(geometry, "Vertices", 0, FALSE); 216 | polygonvertexindex = hxa_fbx_convert_record_find(geometry, "PolygonVertexIndex", 0, FALSE); 217 | if(vertices != NULL && polygonvertexindex != NULL) 218 | { 219 | 220 | file->node_array = realloc(file->node_array, (sizeof *file->node_array) * ++file->node_count); 221 | node = &file->node_array[file->node_count - 1]; 222 | node->meta_data_count = 0; 223 | node->meta_data = NULL; 224 | node->type = HXA_NT_GEOMETRY; 225 | 226 | node->content.geometry.vertex_stack.layer_count = 1; 227 | node->content.geometry.vertex_stack.layers = malloc(sizeof *node->content.geometry.vertex_stack.layers); 228 | node->content.geometry.vertex_stack.layers->components = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS; 229 | node->content.geometry.vertex_count = vertices->property->array_length / 3; 230 | sprintf(node->content.geometry.vertex_stack.layers->name, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME); 231 | if(vertices->property->type == FBX_PROPERTY_TYPE_FLOAT32) 232 | { 233 | node->content.geometry.vertex_stack.layers->type = HXA_LDT_FLOAT; 234 | node->content.geometry.vertex_stack.layers->data.float_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.float_data) * vertices->property->array_length); 235 | memcpy(node->content.geometry.vertex_stack.layers->data.float_data, vertices->property->data.array, (sizeof *node->content.geometry.vertex_stack.layers->data.float_data) * vertices->property->array_length); 236 | } 237 | if(vertices->property->type == FBX_PROPERTY_TYPE_FLOAT64) 238 | { 239 | node->content.geometry.vertex_stack.layers->type = HXA_LDT_DOUBLE; 240 | node->content.geometry.vertex_stack.layers->data.double_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.double_data) * vertices->property->array_length); 241 | memcpy(node->content.geometry.vertex_stack.layers->data.double_data, vertices->property->data.array, (sizeof *node->content.geometry.vertex_stack.layers->data.double_data) * vertices->property->array_length); 242 | 243 | } 244 | 245 | node->content.geometry.corner_stack.layer_count = 1; 246 | node->content.geometry.corner_stack.layers = malloc(sizeof *node->content.geometry.corner_stack.layers); 247 | node->content.geometry.corner_stack.layers->data.int32_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.int32_data) * polygonvertexindex->property->array_length); 248 | memcpy(node->content.geometry.corner_stack.layers->data.int32_data, polygonvertexindex->property->data.array, (sizeof *node->content.geometry.vertex_stack.layers->data.int32_data) * polygonvertexindex->property->array_length); 249 | node->content.geometry.edge_corner_count = polygonvertexindex->property->array_length; 250 | sprintf(node->content.geometry.corner_stack.layers->name, HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME); 251 | node->content.geometry.corner_stack.layers->components = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS; 252 | node->content.geometry.corner_stack.layers->type = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE; 253 | node->content.geometry.edge_stack.layers = 0; 254 | node->content.geometry.edge_stack.layer_count = 0; 255 | node->content.geometry.face_stack.layers = 0; 256 | node->content.geometry.face_stack.layer_count = 0; 257 | node->content.geometry.face_count = 0; 258 | for(j = 0; j < node->content.geometry.edge_corner_count; j++) 259 | if(node->content.geometry.corner_stack.layers->data.int32_data[j] < 0) 260 | node->content.geometry.face_count++; 261 | 262 | j = 0; 263 | for(layer = hxa_fbx_convert_record_find(geometry, "LayerElement", j++, TRUE); layer != NULL; layer = hxa_fbx_convert_record_find(geometry, "LayerElement", j++, TRUE)) 264 | { 265 | printf("Layers found %u %s\n", j, layer->name); 266 | ref = NULL; 267 | param = hxa_fbx_convert_record_find(layer, "MappingInformationType", 0, FALSE); 268 | if(param != NULL) 269 | { 270 | if(hxa_fbx_convert_property_test(param, "ByPolygonVertex")) // Corner layer 271 | { 272 | hxa_fbx_convert_layer_read(layer, &node->content.geometry.corner_stack, node->content.geometry.edge_corner_count); 273 | }else if(hxa_fbx_convert_property_test(param, "ByVertice")) // Vertex Layer 274 | { 275 | hxa_fbx_convert_layer_read(layer, &node->content.geometry.vertex_stack, node->content.geometry.vertex_count); 276 | }else if(hxa_fbx_convert_property_test(param, "ByPolygon")) // Polygon Layer 277 | { 278 | hxa_fbx_convert_layer_read(layer, &node->content.geometry.face_stack, node->content.geometry.face_count); 279 | }else if(hxa_fbx_convert_property_test(param, "ByEdge")) // EdgeLayer 280 | { 281 | hxa_fbx_convert_layer_read(layer, &node->content.geometry.edge_stack, node->content.geometry.edge_corner_count); 282 | } 283 | } 284 | 285 | 286 | } 287 | j = 0; 288 | } 289 | } 290 | return file; 291 | 292 | } -------------------------------------------------------------------------------- /hxa_upi_command_line_interface.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include "hxa.h" 6 | #include "hxa_upi.h" 7 | 8 | #define FALSE 0 9 | #define TRUE !FALSE 10 | 11 | extern void hxa_serialize_free_file(HXAFile *file); 12 | extern HXAFile *hxa_unserialize(hxa_uint8 *buffer, size_t size, int silent); 13 | 14 | int hxa_convert_param_to_int(char *string, int *output) 15 | { 16 | unsigned int i = 0; 17 | *output = 0; 18 | if(string[i] == '-') 19 | i++; 20 | 21 | if(string[i] < '0' && string[i] > '9') 22 | return 0; 23 | *output += (unsigned int)string[i++] - (unsigned int)'0'; 24 | while(string[i] < '0' && string[i] > '9') 25 | { 26 | *output *= 10; 27 | *output += (unsigned int)string[i++] - (unsigned int)'0'; 28 | } 29 | if(string[0] == '-') 30 | *output = -*output; 31 | return i; 32 | } 33 | 34 | int hxa_convert_param_to_double(char *string, double *output) 35 | { 36 | unsigned int i = 0, pos = 0; 37 | double factor = 1.0; 38 | int integer; 39 | if(*string == '-') 40 | pos++; 41 | pos += hxa_convert_param_to_int(&string[pos], &integer); 42 | *output = (double)integer; 43 | if(string[pos] == '.') 44 | { 45 | pos++; 46 | while(string[pos] < '0' && string[pos] > '9') 47 | { 48 | factor *= 0.1; 49 | *output += factor * (double)((unsigned int)string[pos++] - (unsigned int)'0'); 50 | } 51 | } 52 | if(string[0] == '-') 53 | *output = -*output; 54 | return pos; 55 | } 56 | 57 | 58 | int hxa_type_test(char *path, char *type) 59 | { 60 | unsigned int i, j; 61 | for(i = 0; path[i] != 0; i++) 62 | { 63 | if(path[i] == '.') 64 | { 65 | i++; 66 | for(j = 0; type[j] != 0 && path[i + j] != 0 && (path[i + j] == type[j] || path[i + j] + 32 == type[j]); j++); 67 | if(type[j] == 0) 68 | return TRUE; 69 | } 70 | } 71 | return FALSE; 72 | } 73 | 74 | extern int hxa_load_png(HXAFile *file, char *file_name); 75 | extern void hxa_type_convert_gen(); 76 | 77 | unsigned int hxa_upi_param_count[] = {1, // HXA_UPI_IPT_BOOLEAN 78 | 1, // HXA_UPI_IPT_SIGNED_INTEGER 79 | 1, // HXA_UPI_IPT_UNSIGNED_INTEGER 80 | 1, // HXA_UPI_IPT_DOUBLE_BOUND 81 | 1, // HXA_UPI_IPT_DOUBLE_UNBOUND 82 | 2, // HXA_UPI_IPT_POS_2D 83 | 3, // HXA_UPI_IPT_POS_3D 84 | 2, // HXA_UPI_IPT_VECTOR_2D 85 | 3, // HXA_UPI_IPT_VECTOR_3D 86 | 16, // HXA_UPI_IPT_MATRIX 87 | 3, // HXA_UPI_IPT_COLOR 88 | 1, // HXA_UPI_IPT_TEXT 89 | 1, // HXA_UPI_IPT_PATH_READ 90 | 1, // HXA_UPI_IPT_PATH_WRITE 91 | 1, // HXA_UPI_IPT_SELECT 92 | 1, // HXA_UPI_IPT_HXA_READ 93 | 1}; // HXA_UPI_IPT_HXA_CONSUME 94 | 95 | HXAFile *hxa_upi_parse(HxAUPIPlugin *plugins, unsigned int plugin_count, int argc, char **argv, int *arg_pos) 96 | { 97 | HXAUPIInterfaceParam *params = NULL; 98 | HXAFile *output; 99 | HxAUPIPlugin *plugin; 100 | void *instance = NULL; 101 | int integer; 102 | unsigned int i, j; 103 | for(i = 0; i < plugin_count && 0 != strcmp(argv[*arg_pos], plugins[i].name); i++); 104 | if(i < plugin_count) 105 | { 106 | (*arg_pos)++; 107 | plugin = &plugins[i]; 108 | if(plugin->param_count != 0) 109 | { 110 | params = malloc((sizeof *params) * plugin->param_count); 111 | memcpy(params, plugin->params, (sizeof *params) * plugin->param_count); 112 | for(i = 0; i < plugin->param_count; i++) 113 | { 114 | if(hxa_upi_param_count[plugin->params[i].type] + *arg_pos > argc) 115 | { 116 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid boolean value\n", i, plugin->name, argv[*arg_pos]); 117 | exit(0); 118 | } 119 | switch(plugin->params[i].type) 120 | { 121 | case HXA_UPI_IPT_BOOLEAN : 122 | if(0 == strcmp(argv[*arg_pos], "TRUE") || 0 == strcmp(argv[*arg_pos], "true") || 0 == strcmp(argv[*arg_pos], "t")) 123 | { 124 | params[i].content.boolean = TRUE; 125 | }else if(0 == strcmp(argv[*arg_pos], "FALSE") || 0 == strcmp(argv[*arg_pos], "false") || 0 == strcmp(argv[*arg_pos], "f")) 126 | { 127 | params[i].content.boolean = FALSE; 128 | }else if(0 == hxa_convert_param_to_int(argv[*arg_pos], &integer)) 129 | { 130 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid boolean value\n", i, plugin->name, argv[*arg_pos]); 131 | exit(0); 132 | }else 133 | params[i].content.boolean = integer != FALSE; 134 | break; 135 | case HXA_UPI_IPT_SIGNED_INTEGER : 136 | if(0 == hxa_convert_param_to_int(argv[*arg_pos], ¶ms[i].content.signed_integer)) 137 | { 138 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid integer value\n", i, plugin->name, argv[*arg_pos]); 139 | exit(0); 140 | } 141 | break; 142 | case HXA_UPI_IPT_UNSIGNED_INTEGER : 143 | if(0 == hxa_convert_param_to_int(argv[*arg_pos], ¶ms[i].content.unsigned_integer)) 144 | { 145 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid integer value\n", i, plugin->name, argv[*arg_pos]); 146 | exit(0); 147 | } 148 | break; 149 | case HXA_UPI_IPT_DOUBLE_BOUND : 150 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.double_value)) 151 | { 152 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid floating point value\n", i, plugin->name, argv[*arg_pos]); 153 | exit(0); 154 | } 155 | if(params[i].content.double_value > 1.0) 156 | params[i].content.double_value = 1.0; 157 | if(params[i].content.double_value < 0.0) 158 | params[i].content.double_value = 0.0; 159 | break; 160 | case HXA_UPI_IPT_DOUBLE_UNBOUND : 161 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.double_value)) 162 | { 163 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid floating point value\n", i, plugin->name, argv[*arg_pos]); 164 | exit(0); 165 | } 166 | break; 167 | case HXA_UPI_IPT_POS_2D : 168 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.point_2d[0]) || 169 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 1], ¶ms[i].content.point_2d[1])) 170 | { 171 | printf("Error: Argument %u of plugin %s \"%s\" \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos], argv[*arg_pos + 1]); 172 | exit(0); 173 | } 174 | break; 175 | case HXA_UPI_IPT_POS_3D : 176 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.point_3d[0]) || 177 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 1], ¶ms[i].content.point_3d[1]) || 178 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 2], ¶ms[i].content.point_3d[2])) 179 | { 180 | printf("Error: Argument %u of plugin %s \"%s\" \"%s\" \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos], argv[*arg_pos + 1], argv[*arg_pos + 2]); 181 | exit(0); 182 | } 183 | break; 184 | case HXA_UPI_IPT_VECTOR_2D : 185 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.vector_2d[0]) || 186 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 1], ¶ms[i].content.vector_2d[1])) 187 | { 188 | printf("Error: Argument %u of plugin %s \"%s\" \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos], argv[*arg_pos + 1]); 189 | exit(0); 190 | } 191 | break; 192 | case HXA_UPI_IPT_VECTOR_3D : 193 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.vector_3d[0]) || 194 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 1], ¶ms[i].content.vector_3d[1]) || 195 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 2], ¶ms[i].content.vector_3d[2])) 196 | { 197 | printf("Error: Argument %u of plugin %s \"%s\" \"%s\" \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos], argv[*arg_pos + 1], argv[*arg_pos + 2]); 198 | exit(0); 199 | } 200 | break; 201 | case HXA_UPI_IPT_MATRIX : 202 | for(j = 0; j < 16 && 0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.matrix[j]); j++); 203 | if(j < 16) 204 | { 205 | printf("Error: Argument %u of plugin %s \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos + j]); 206 | exit(0); 207 | } 208 | break; 209 | case HXA_UPI_IPT_COLOR : 210 | if(0 == hxa_convert_param_to_double(argv[*arg_pos], ¶ms[i].content.color[0]) || 211 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 1], ¶ms[i].content.color[1]) || 212 | 0 == hxa_convert_param_to_double(argv[*arg_pos + 2], ¶ms[i].content.color[2])) 213 | { 214 | printf("Error: Argument %u of plugin %s \"%s\" \"%s\" \"%s\" are not valid floating point values\n", i, plugin->name, argv[*arg_pos], argv[*arg_pos + 1], argv[*arg_pos + 2]); 215 | exit(0); 216 | } 217 | break; 218 | case HXA_UPI_IPT_TEXT : 219 | case HXA_UPI_IPT_PATH_READ : 220 | case HXA_UPI_IPT_PATH_WRITE : 221 | plugin->params[i].content.text = argv[*arg_pos]; 222 | break; 223 | case HXA_UPI_IPT_SELECT : 224 | for(params[i].content.select.selected = 0; 225 | params[i].content.select.selected < params[i].content.select.option_count && 226 | !strcmp(argv[*arg_pos], plugin->params[i].content.select.option_names[plugin->params[i].content.select.selected]); 227 | params[i].content.select.selected++); 228 | if(params[i].content.select.selected == params[i].content.select.option_count) 229 | { 230 | if(0 == hxa_convert_param_to_int(argv[*arg_pos], ¶ms[i].content.select.selected)) 231 | { 232 | printf("Error: Argument %u of plugin %s \"%s\" is not a valid integer value or option string\n", i, plugin->name, argv[*arg_pos]); 233 | exit(0); 234 | } 235 | } 236 | break; 237 | case HXA_UPI_IPT_HXA_READ : 238 | case HXA_UPI_IPT_HXA_CONSUME : 239 | params[i].content.hxa = hxa_upi_parse(plugins, plugin_count, argc, argv, arg_pos); 240 | (*arg_pos)--; 241 | break; 242 | } 243 | *arg_pos += hxa_upi_param_count[plugin->params[i].type]; 244 | } 245 | } 246 | if(plugin->instance_create_func != NULL) 247 | instance = plugin->instance_create_func(params, plugin->user_data); 248 | output = plugin->execute_func(params, instance, plugin->user_data); 249 | if(plugin->instance_destroy_func != NULL && instance != NULL) 250 | plugin->instance_destroy_func(params, plugin->user_data, instance); 251 | for(i = 0; i < plugin->param_count; i++) 252 | if(plugin->params[i].type == HXA_UPI_IPT_HXA_READ) 253 | hxa_serialize_free_file(plugin->params[i].content.hxa); 254 | if(plugin->param_count != 0) 255 | free(params); 256 | }else 257 | { 258 | unsigned char *buffer; 259 | unsigned long long allocation, i; 260 | FILE *f; 261 | f = fopen(argv[*arg_pos], "rb"); 262 | if(f == NULL) 263 | { 264 | printf("Error: Argument \"%s\" is not a valid plugin or HxA file.\n", argv[*arg_pos]); 265 | exit(0); 266 | } 267 | fseek(f, 0, SEEK_END); 268 | allocation = ftell(f); 269 | if(allocation == 0) 270 | { 271 | fclose(f); 272 | printf("Error: Argument \"%s\" file is empty.\n", argv[*arg_pos]); 273 | exit(0); 274 | } 275 | (*arg_pos)++; 276 | rewind(f); 277 | buffer = malloc(allocation); 278 | memset(buffer, 0, allocation); 279 | fread(buffer, 1, allocation, f); 280 | fclose(f); 281 | output = hxa_unserialize(buffer, allocation, FALSE); 282 | free(buffer); 283 | if(output == NULL) 284 | exit(0); 285 | } 286 | return output; 287 | } 288 | 289 | void hxa_upi_help(HxAUPIPlugin *plugins) 290 | { 291 | char *typen_names[] = {"Boolean", 292 | "Signed integer", 293 | "Unsigned integer", 294 | "value between 0 and 1", 295 | "floating point value", 296 | "2D position", 297 | "3D Position", 298 | "2D vector", 299 | "3D vector", 300 | "4x4 matrix", 301 | "RGB color", 302 | "Text String", 303 | "Load path", 304 | "Save path", 305 | "option select", 306 | "HxA structure or file", 307 | "HxA structure or file"}; 308 | unsigned int i, j; 309 | printf("Command: %s\n", plugins->name); 310 | printf("\tDescription: %s\n", plugins->descrtiption); 311 | if(plugins->param_count != 0) 312 | printf("\tParameters:\n"); 313 | for(i = 0; i < plugins->param_count; i++) 314 | { 315 | printf("\t\t-%s : %s\n", plugins->params[i].name, typen_names[plugins->params[i].type]); 316 | if(plugins->params[i].type == HXA_UPI_IPT_SELECT) 317 | { 318 | for(j = 0; j < plugins->params[i].content.select.option_count; j++) 319 | printf("\t\t\toption %u : %s\n", j, plugins->params[i].content.select.option_names[j]); 320 | 321 | } 322 | printf("\t\t Param description: %s\n", plugins->params[i].description); 323 | } 324 | if(plugins->has_output) 325 | printf("\tOutputs HxA structure\n"); 326 | } 327 | 328 | int main(int argc, char **argv) 329 | { 330 | HXAFile *file; 331 | HxAUPIPlugin *plugins; 332 | char *path = ".\\"; 333 | unsigned int i, used = 1, plugin_count = 0; 334 | if(used < argc && 0 == strcmp(argv[used], "path")) 335 | { 336 | if(argc < 3) 337 | { 338 | printf("Error: Missing path parameter.\n"); 339 | return FALSE; 340 | } 341 | path = argv[used + 1]; 342 | used += 2; 343 | } 344 | plugins = hxa_upi_host_load_directory(path, &plugin_count); 345 | if(plugin_count == 0) 346 | { 347 | printf("Error: No UBI plugins found at path: %s\n", path); 348 | return FALSE; 349 | } 350 | if(used == argc || (used + 1 == argc && 0 == 0 == strcmp(argv[used], "help"))) 351 | { 352 | printf("Command list:\n"); 353 | printf("-------------\n"); 354 | 355 | for(i = 0; i < plugin_count; i++) 356 | hxa_upi_help(&plugins[i]); 357 | return TRUE; 358 | } 359 | if(0 == strcmp(argv[used], "help")) 360 | { 361 | used++; 362 | for(i = 0; i < plugin_count; i++) 363 | { 364 | if(0 == strcmp(argv[used], plugins[i].name)) 365 | { 366 | hxa_upi_help(&plugins[i]); 367 | return TRUE; 368 | } 369 | } 370 | printf("Error: No UBI plugins with the name %s found.\n", argv[used]); 371 | return FALSE; 372 | } 373 | 374 | file = hxa_upi_parse(plugins, plugin_count, argc, argv, &used); 375 | if(file != NULL) 376 | hxa_serialize_free_file(file); 377 | printf("Sucsess!!"); 378 | return TRUE; 379 | } 380 | -------------------------------------------------------------------------------- /hxa_util_triangulate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "hxa.h" 6 | #include "hxa_utils.h" 7 | 8 | #define FALSE 0 9 | #define TRUE !FALSE 10 | 11 | typedef enum{ 12 | HXA_UTIL_TEC_VALID, 13 | HXA_UTIL_TEC_CONCAVE, 14 | HXA_UTIL_TEC_OVERLAPING 15 | }HxATrinagulateEdgeCategory; 16 | 17 | typedef struct{ 18 | int vertex; 19 | unsigned int origin; 20 | HxATrinagulateEdgeCategory category; 21 | double weight; 22 | unsigned int worst_vertex; 23 | }HxATrinagulateEdge; 24 | 25 | 26 | void hxa_util_triangulate_ngon_edge_evaluate(HxATrinagulateEdge *edges, unsigned int edge_count, unsigned int active, double *vertex) 27 | { 28 | double normal[3], v0[3], v1[3], v2[3], t0[3], t1[3], t2[3], *base0, *base1, *middle, *test, f; 29 | unsigned int i, first = TRUE; 30 | base0 = &vertex[edges[active].vertex * 3]; 31 | middle = &vertex[edges[(active + 1) % edge_count].vertex * 3]; 32 | base1 = &vertex[edges[(active + 2) % edge_count].vertex * 3]; 33 | 34 | t0[0] = base0[0] - base1[0]; 35 | t0[1] = base0[1] - base1[1]; 36 | t0[2] = base0[2] - base1[2]; 37 | t1[0] = middle[0] - base1[0]; 38 | t1[1] = middle[1] - base1[1]; 39 | t1[2] = middle[2] - base1[2]; 40 | normal[0] = t0[1] * t1[2] - t0[2] * t1[1]; 41 | normal[1] = t0[2] * t1[0] - t0[0] * t1[2]; 42 | normal[2] = t0[0] * t1[1] - t0[1] * t1[0]; 43 | f = sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); 44 | normal[0] /= f; 45 | normal[1] /= f; 46 | normal[2] /= f; 47 | 48 | v0[0] = base1[0] - base0[0]; 49 | v0[1] = base1[1] - base0[1]; 50 | v0[2] = base1[2] - base0[2]; 51 | v1[0] = base0[0] - middle[0]; 52 | v1[1] = base0[1] - middle[1]; 53 | v1[2] = base0[2] - middle[2]; 54 | v2[0] = middle[0] - base1[0]; 55 | v2[1] = middle[1] - base1[1]; 56 | v2[2] = middle[2] - base1[2]; 57 | 58 | t0[0] = v0[1] * normal[2] - v0[2] * normal[1]; 59 | t0[1] = v0[2] * normal[0] - v0[0] * normal[2]; 60 | t0[2] = v0[0] * normal[1] - v0[1] * normal[0]; 61 | 62 | t1[0] = v1[1] * normal[2] - v1[2] * normal[1]; 63 | t1[1] = v1[2] * normal[0] - v1[0] * normal[2]; 64 | t1[2] = v1[0] * normal[1] - v1[1] * normal[0]; 65 | 66 | t2[0] = v2[1] * normal[2] - v2[2] * normal[1]; 67 | t2[1] = v2[2] * normal[0] - v2[0] * normal[2]; 68 | t2[2] = v2[0] * normal[1] - v2[1] * normal[0]; 69 | 70 | edges[active].category = HXA_UTIL_TEC_VALID; 71 | edges[active].weight = -1.0; 72 | edges[active].worst_vertex = -1; 73 | for(i = 0; i < edge_count - 3; i++) 74 | { 75 | test = &vertex[edges[(active + i + 3) % edge_count].vertex * 3]; 76 | f = t0[0] * (test[0] - base0[0]) + t0[1] * (test[1] - base0[1]) + t0[2] * (test[2] - base0[2]); 77 | if(f > 0.0) 78 | { 79 | if(t1[0] * (test[0] - base0[0]) + t1[1] * (test[1] - base0[1]) + t1[2] * (test[2] - base0[2]) > 0 && 80 | t2[0] * (test[0] - base1[0]) + t2[1] * (test[1] - base1[1]) + t2[2] * (test[2] - base1[2]) > 0) 81 | { 82 | f = normal[0] * (test[0] - base0[0]) + normal[1] * (test[1] - base0[1]) + normal[2] * (test[2] - base0[2]); 83 | if(f < 0) 84 | f = f * -0.1; 85 | if(edges[active].category < HXA_UTIL_TEC_OVERLAPING || f > edges[active].weight) 86 | { 87 | edges[active].category = HXA_UTIL_TEC_OVERLAPING; 88 | edges[active].weight = f; 89 | edges[active].worst_vertex = edges[(i + 3) % edge_count].vertex; 90 | } 91 | }else if(edges[active].category < HXA_UTIL_TEC_CONCAVE || (f > edges[active].weight && edges[active].category != HXA_UTIL_TEC_OVERLAPING)) 92 | { 93 | edges[active].category = HXA_UTIL_TEC_CONCAVE; 94 | edges[active].weight = -f; 95 | edges[active].worst_vertex = edges[(i + 3) % edge_count].vertex; 96 | } 97 | } 98 | } 99 | if(edges[active].category == HXA_UTIL_TEC_VALID) 100 | { 101 | f = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]); 102 | v1[0] /= f; 103 | v1[1] /= f; 104 | v1[2] /= f; 105 | f = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]); 106 | v2[0] /= f; 107 | v2[1] /= f; 108 | v2[2] /= f; 109 | edges[active].weight = 1 + v1[0] * -v2[0] + v1[1] * -v2[1] + v1[2] * -v2[2]; 110 | } 111 | } 112 | 113 | 114 | unsigned int hxa_util_triangulate_ngon(int *ref_ngon, unsigned int *ref_output, unsigned int *origin_output, unsigned int origin_start, unsigned int count, double *vertex, unsigned int vertex_length) 115 | { 116 | HxATrinagulateEdge edge_buffers[1024], *e; 117 | unsigned int i, found, output_count = 0, update; 118 | 119 | if(count < 1024) 120 | e = edge_buffers; 121 | else 122 | e = malloc((sizeof *e) * count); 123 | for(i = 0; i < count - 1; i++) 124 | { 125 | e[i].vertex = ref_ngon[i]; 126 | e[i].origin = origin_start + i; 127 | } 128 | e[i].vertex = (unsigned int)(-ref_ngon[i] - 1); 129 | e[i].origin = origin_start + i; 130 | 131 | for(i = 0; i < count; i++) 132 | hxa_util_triangulate_ngon_edge_evaluate(e, count, i, vertex); 133 | 134 | while(TRUE) 135 | { 136 | found = 0; 137 | for(i = 1; i < count; i++) 138 | if(e[i].category < e[found].category || (e[i].category == e[found].category && e[i].weight > e[found].weight)) 139 | found = i; 140 | ref_output[output_count] = e[found].vertex; 141 | ref_output[output_count + 1] = e[(found + 1) % count].vertex; 142 | ref_output[output_count + 2] = -e[(found + 2) % count].vertex - 1; 143 | if(origin_output != NULL) 144 | { 145 | origin_output[output_count] = e[found].origin; 146 | origin_output[output_count + 1] = e[(found + 1) % count].origin; 147 | origin_output[output_count + 2] = e[(found + 2) % count].origin; 148 | } 149 | output_count += 3; 150 | update = e[(found + 1) % count].vertex; 151 | found = (found + 1) % count; 152 | for(i = found + 1; i < count; i++) 153 | e[i - 1] = e[i]; 154 | count--; 155 | if(count == 3) 156 | break; 157 | hxa_util_triangulate_ngon_edge_evaluate(e, count, (found + count - 2) % count, vertex); 158 | hxa_util_triangulate_ngon_edge_evaluate(e, count, (found + count - 1) % count, vertex); 159 | for(i = 0; i < count; i++) 160 | if(e[i].worst_vertex == update) 161 | hxa_util_triangulate_ngon_edge_evaluate(e, count, i, vertex); 162 | } 163 | ref_output[output_count] = e[0].vertex; 164 | ref_output[output_count + 1] = e[1].vertex; 165 | ref_output[output_count + 2] = -e[2].vertex - 1; 166 | if(origin_output != NULL) 167 | { 168 | origin_output[output_count] = e[0].origin; 169 | origin_output[output_count + 1] = e[1].origin; 170 | origin_output[output_count + 2] = e[2].origin; 171 | } 172 | output_count += 3; 173 | if(e != edge_buffers) 174 | free(e); 175 | return output_count; 176 | } 177 | 178 | void hxa_util_triangulate_re_ref_layer(HXALayer *layers, unsigned int count, unsigned int *re_ref) 179 | { 180 | unsigned int i, j, components; 181 | components = layers->components; 182 | switch(layers->type) 183 | { 184 | case HXA_LDT_UINT8 : 185 | { 186 | unsigned char *read, *write; 187 | read = layers->data.uint8_data; 188 | write = malloc((sizeof *write) * components * count); 189 | layers->data.uint8_data = write; 190 | for(i = 0; i < count; i++) 191 | for(j = 0; j < components; j++) 192 | write[i * components + j] = read[re_ref[i] * components + j]; 193 | free(read); 194 | } 195 | break; 196 | case HXA_LDT_INT32 : 197 | { 198 | int *read, *write; 199 | read = layers->data.int32_data; 200 | write = malloc((sizeof *write) * components * count); 201 | layers->data.int32_data = write; 202 | for(i = 0; i < count; i++) 203 | for(j = 0; j < components; j++) 204 | write[i * components + j] = read[re_ref[i] * components + j]; 205 | free(read); 206 | } 207 | break; 208 | case HXA_LDT_FLOAT : 209 | { 210 | float *read, *write; 211 | read = layers->data.float_data; 212 | write = malloc((sizeof *write) * components * count); 213 | layers->data.float_data = write; 214 | for(i = 0; i < count; i++) 215 | for(j = 0; j < components; j++) 216 | write[i * components + j] = read[re_ref[i] * components + j]; 217 | free(read); 218 | } 219 | break; 220 | case HXA_LDT_DOUBLE : 221 | { 222 | double *read, *write; 223 | read = layers->data.double_data; 224 | write = malloc((sizeof *write) * components * count); 225 | layers->data.double_data = write; 226 | for(i = 0; i < count; i++) 227 | for(j = 0; j < components; j++) 228 | write[i * components + j] = read[re_ref[i] * components + j]; 229 | free(read); 230 | } 231 | break; 232 | } 233 | } 234 | 235 | extern int hxa_corner_get_next(int *ref, unsigned int corner); 236 | 237 | void hxa_util_triangulate_re_ref_edge_layer(HXALayer *layers, unsigned int count, unsigned int *new_ref, unsigned int *old_ref, unsigned int *re_ref) 238 | { 239 | unsigned int i, j, components; 240 | int new_next, old_next; 241 | components = layers->components; 242 | switch(layers->type) 243 | { 244 | case HXA_LDT_UINT8 : 245 | { 246 | unsigned char *read, *write; 247 | read = layers->data.uint8_data; 248 | write = malloc((sizeof *write) * components * count); 249 | layers->data.uint8_data = write; 250 | for(i = 0; i < count; i++) 251 | { 252 | old_next = old_ref[hxa_corner_get_next(old_ref, i)]; 253 | new_next = new_ref[hxa_corner_get_next(new_ref, i)]; 254 | if(old_next < 0) 255 | old_next = -old_next - 1; 256 | if(new_next < 0) 257 | new_next = -new_next - 1; 258 | if(old_next == new_next) 259 | { 260 | for(j = 0; j < components; j++) 261 | write[i * components + j] = read[re_ref[i] * components + j]; 262 | }else 263 | for(j = 0; j < components; j++) 264 | write[i * components + j] = 0; 265 | } 266 | free(read); 267 | } 268 | break; 269 | case HXA_LDT_INT32 : 270 | { 271 | int *read, *write; 272 | read = layers->data.int32_data; 273 | write = malloc((sizeof *write) * components * count); 274 | layers->data.int32_data = write; 275 | for(i = 0; i < count; i++) 276 | { 277 | old_next = old_ref[hxa_corner_get_next(old_ref, i)]; 278 | new_next = new_ref[hxa_corner_get_next(new_ref, i)]; 279 | if(old_next < 0) 280 | old_next = -old_next - 1; 281 | if(new_next < 0) 282 | new_next = -new_next - 1; 283 | if(old_next == new_next) 284 | { 285 | for(j = 0; j < components; j++) 286 | write[i * components + j] = read[re_ref[i] * components + j]; 287 | }else 288 | for(j = 0; j < components; j++) 289 | write[i * components + j] = 0; 290 | } 291 | free(read); 292 | } 293 | break; 294 | case HXA_LDT_FLOAT : 295 | { 296 | float *read, *write; 297 | read = layers->data.float_data; 298 | write = malloc((sizeof *write) * components * count); 299 | layers->data.float_data = write; 300 | for(i = 0; i < count; i++) 301 | { 302 | old_next = old_ref[hxa_corner_get_next(old_ref, i)]; 303 | new_next = new_ref[hxa_corner_get_next(new_ref, i)]; 304 | if(old_next < 0) 305 | old_next = -old_next - 1; 306 | if(new_next < 0) 307 | new_next = -new_next - 1; 308 | if(old_next == new_next) 309 | { 310 | for(j = 0; j < components; j++) 311 | write[i * components + j] = read[re_ref[i] * components + j]; 312 | }else 313 | for(j = 0; j < components; j++) 314 | write[i * components + j] = 0; 315 | } 316 | free(read); 317 | } 318 | break; 319 | case HXA_LDT_DOUBLE : 320 | { 321 | double *read, *write; 322 | read = layers->data.double_data; 323 | write = malloc((sizeof *write) * components * count); 324 | layers->data.double_data = write; 325 | for(i = 0; i < count; i++) 326 | { 327 | old_next = old_ref[hxa_corner_get_next(old_ref, i)]; 328 | new_next = new_ref[hxa_corner_get_next(new_ref, i)]; 329 | if(old_next < 0) 330 | old_next = -old_next - 1; 331 | if(new_next < 0) 332 | new_next = -new_next - 1; 333 | if(old_next == new_next) 334 | { 335 | for(j = 0; j < components; j++) 336 | write[i * components + j] = read[re_ref[i] * components + j]; 337 | }else 338 | for(j = 0; j < components; j++) 339 | write[i * components + j] = 0; 340 | } 341 | free(read); 342 | } 343 | break; 344 | } 345 | } 346 | 347 | void hxa_util_triangulate_node(HXANode *node, unsigned int max_sides) 348 | { 349 | unsigned int i, j, k, poly_count, ref_count, sides, *corner_reference, *poly_reference, count; 350 | double *vertex; 351 | float *vertex_f = NULL; 352 | int *ref, *new_ref; 353 | if(node->type != HXA_NT_GEOMETRY) 354 | return; 355 | if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT) 356 | { 357 | vertex_f = node->content.geometry.vertex_stack.layers[0].data.float_data; 358 | count = node->content.geometry.vertex_count * 3; 359 | vertex = malloc((sizeof *vertex) * count); 360 | for(i = 0; i < count; i++) 361 | vertex[i] = (double)vertex_f[i]; 362 | }else 363 | vertex = node->content.geometry.vertex_stack.layers[0].data.double_data; 364 | ref = node->content.geometry.corner_stack.layers[0].data.int32_data; 365 | poly_count = ref_count = 0; 366 | for(i = 0; i < node->content.geometry.edge_corner_count; i += sides) 367 | { 368 | for(sides = 0; ref[i + sides] >= 0; sides++); 369 | sides++; 370 | if(sides > max_sides) 371 | { 372 | poly_count += sides + 1 - 3; 373 | ref_count += (sides + 1 - 3) * 3; 374 | }else 375 | { 376 | poly_count++; 377 | ref_count += sides; 378 | } 379 | } 380 | corner_reference = malloc((sizeof *corner_reference) * ref_count); 381 | new_ref = malloc((sizeof *new_ref) * ref_count); 382 | poly_reference = malloc((sizeof *poly_reference) * poly_count); 383 | poly_count = ref_count = 0; 384 | 385 | count = node->content.geometry.vertex_count; 386 | for(i = k = 0; i < node->content.geometry.edge_corner_count; i += sides) 387 | { 388 | for(sides = 0; ref[i + sides] >= 0; sides++); 389 | sides++; 390 | if(sides > max_sides) 391 | { 392 | hxa_util_triangulate_ngon(&ref[i], &new_ref[ref_count], &corner_reference[ref_count], i, sides, vertex, count); 393 | ref_count += (sides + 1 - 3) * 3; 394 | for(j = max_sides - 1; j < sides; j++) 395 | poly_reference[poly_count++] = k; 396 | }else 397 | { 398 | for(j = 0; j < sides; j++) 399 | { 400 | new_ref[ref_count] = ref[i + j]; 401 | corner_reference[ref_count++] = i + j; 402 | } 403 | poly_reference[poly_count++] = k; 404 | } 405 | k++; 406 | } 407 | node->content.geometry.corner_stack.layers[0].data.int32_data = new_ref; 408 | for(i = 0; i < ref_count; i++) 409 | printf("corner_reference[%u] = %u\n", i, corner_reference[i]); 410 | for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++) 411 | hxa_util_triangulate_re_ref_layer(&node->content.geometry.corner_stack.layers[i], ref_count, corner_reference); 412 | for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++) 413 | hxa_util_triangulate_re_ref_edge_layer(&node->content.geometry.edge_stack.layers[i], ref_count, new_ref, ref, corner_reference); 414 | for(i = 0; i < node->content.geometry.face_stack.layer_count; i++) 415 | hxa_util_triangulate_re_ref_layer(&node->content.geometry.face_stack.layers[i], poly_count, poly_reference); 416 | node->content.geometry.face_count = poly_count; 417 | node->content.geometry.edge_corner_count = ref_count; 418 | free(ref); 419 | free(corner_reference); 420 | free(poly_reference); 421 | if(vertex_f != NULL) 422 | free(vertex); 423 | } --------------------------------------------------------------------------------