mirror of
https://github.com/quelsolaar/HxA
synced 2025-02-01 09:58:42 -05:00
494 lines
15 KiB
C
494 lines
15 KiB
C
#define _CRT_SECURE_NO_WARNINGS
|
|
#pragma warning(disable:4996)
|
|
#pragma warning(disable:4703)
|
|
#pragma warning(disable:4996)
|
|
#pragma warning(disable:4664)
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "hxa.h"
|
|
#include "forge.h"we
|
|
|
|
#define FALSE 0
|
|
#define TRUE !FALSE
|
|
|
|
void hxa_util_free_stack(HXALayerStack *stack)
|
|
{
|
|
unsigned int i;
|
|
for(i = 0; i < stack->layer_count; i++)
|
|
free(stack->layers[i].data.uint8_data);
|
|
if(stack->layer_count != 0)
|
|
free(stack->layers);
|
|
}
|
|
|
|
void hxa_util_free_meta(HXAMeta *meta)
|
|
{
|
|
unsigned int i;
|
|
switch(meta->type)
|
|
{
|
|
case HXA_MDT_INT64 :
|
|
free(meta->value.int64_value);
|
|
break;
|
|
case HXA_MDT_DOUBLE :
|
|
free(meta->value.double_value);
|
|
break;
|
|
case HXA_MDT_NODE :
|
|
free(meta->value.node_value);
|
|
break;
|
|
case HXA_MDT_TEXT :
|
|
free(meta->value.text_value);
|
|
break;
|
|
case HXA_MDT_BINARY :
|
|
free(meta->value.bin_value);
|
|
break;
|
|
case HXA_MDT_META :
|
|
for(i = 0; i < meta->array_length; i++)
|
|
hxa_util_free_meta(&(((HXAMeta *)meta->value.array_of_meta)[i]));
|
|
free(meta->value.array_of_meta);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void hxa_util_free_node_content(HXANode *node)
|
|
{
|
|
unsigned int i;
|
|
for(i = 0; i < node->meta_data_count; i++)
|
|
hxa_util_free_meta(&node->meta_data[i]);
|
|
if(node->meta_data_count != 0)
|
|
free(node->meta_data);
|
|
switch(node->type)
|
|
{
|
|
case HXA_NT_GEOMETRY :
|
|
hxa_util_free_stack(&node->content.geometry.corner_stack);
|
|
hxa_util_free_stack(&node->content.geometry.edge_stack);
|
|
hxa_util_free_stack(&node->content.geometry.vertex_stack);
|
|
hxa_util_free_stack(&node->content.geometry.face_stack);
|
|
break;
|
|
case HXA_NT_IMAGE :
|
|
hxa_util_free_stack(&node->content.image.image_stack);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void hxa_util_free_file(HXAFile *file)
|
|
{
|
|
unsigned int i;
|
|
for(i = 0; i < file->node_count; i++)
|
|
hxa_util_free_node_content(&file->node_array[i]);
|
|
if(file->node_count != 0)
|
|
free(file->node_array);
|
|
free(file);
|
|
}
|
|
|
|
int hxa_load_data(FILE *f, void *buffer, size_t length, char *file_name, int silent)
|
|
{
|
|
unsigned int read;
|
|
read = fread(buffer, sizeof(hxa_uint8), length, f);
|
|
if(length != read)
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s unexpectedly ended\n", file_name);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
int hxa_load_name(FILE *f, char *file_name, char *name, int silent)
|
|
{
|
|
hxa_uint8 length;
|
|
if(hxa_load_data(f, &length, sizeof(hxa_uint8), file_name, silent))
|
|
{
|
|
if(hxa_load_data(f, name, length, file_name, silent))
|
|
{
|
|
name[length] = 0;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
char *hxa_load_string(FILE *f, char *file_name, int silent)
|
|
{
|
|
char *string;
|
|
hxa_uint32 length;
|
|
if(hxa_load_data(f, &length, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
string = malloc(length + 1);
|
|
if(hxa_load_data(f, string, length, file_name, silent))
|
|
{
|
|
string[length] = 0;
|
|
return string;
|
|
}
|
|
free(string);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int hxa_load_meta(FILE *f, char *file_name, HXAMeta **meta, hxa_uint32 *count, int silent)
|
|
{
|
|
HXAMeta *m;
|
|
unsigned int i, j, c;
|
|
hxa_uint8 type;
|
|
c = *count;
|
|
*count = 0;
|
|
m = malloc((sizeof *m) * c);
|
|
*meta = m;
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if(!hxa_load_name(f, file_name, m->name, silent))
|
|
return FALSE;
|
|
if(!hxa_load_data(f, &type, sizeof(hxa_uint8), file_name, silent) ||
|
|
!hxa_load_data(f, &m->array_length, sizeof(hxa_uint32), file_name, silent))
|
|
return FALSE;
|
|
if(type >= HXA_MDT_COUNT)
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s has meta data of type %u. There is only %u types of meta data\n", file_name, type, HXA_MDT_COUNT);
|
|
return FALSE;
|
|
}
|
|
m->type = type;
|
|
switch(type)
|
|
{
|
|
case HXA_MDT_INT64 :
|
|
m->value.int64_value = malloc(sizeof(hxa_int64) * m->array_length);
|
|
if(!hxa_load_data(f, m->value.int64_value, sizeof(hxa_int64) * m->array_length, file_name, silent))
|
|
return FALSE;
|
|
break;
|
|
case HXA_MDT_DOUBLE :
|
|
m->value.double_value = malloc(sizeof(double) * m->array_length);
|
|
if(!hxa_load_data(f, m->value.double_value, sizeof(double) * m->array_length, file_name, silent))
|
|
return FALSE;
|
|
break;
|
|
case HXA_MDT_NODE :
|
|
m->value.node_value = malloc(sizeof(hxa_uint32) * m->array_length);
|
|
if(!hxa_load_data(f, m->value.node_value, sizeof(hxa_uint32) * m->array_length, file_name, silent))
|
|
return FALSE;
|
|
break;
|
|
case HXA_MDT_TEXT :
|
|
m->value.text_value = malloc(sizeof(char) * (m->array_length));
|
|
if(!hxa_load_data(f, m->value.text_value, sizeof(hxa_uint8) * m->array_length, file_name, silent))
|
|
return FALSE;
|
|
m->value.text_value[m->array_length - 1] = 0;
|
|
break;
|
|
case HXA_MDT_BINARY :
|
|
m->value.bin_value = malloc(sizeof(char) * (m->array_length));
|
|
if(!hxa_load_data(f, m->value.bin_value, sizeof(hxa_uint8) * m->array_length, file_name, silent))
|
|
return FALSE;
|
|
break;
|
|
case HXA_MDT_META :
|
|
m->value.array_of_meta = NULL;
|
|
if(!hxa_load_meta(f, file_name, (HXAMeta **)&m->value.array_of_meta, &m->array_length, silent))
|
|
return FALSE;
|
|
break;
|
|
}
|
|
(*count)++;
|
|
m++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
int hxa_load_layer_stack(FILE *f, char *file_name, HXALayerStack *stack, unsigned int length, int silent)
|
|
{
|
|
const type_sizes[] = {sizeof(hxa_uint8), sizeof(hxa_uint32), sizeof(float), sizeof(double)};
|
|
hxa_uint32 stack_count, i;
|
|
hxa_uint8 type;
|
|
size_t size;
|
|
if(!hxa_load_data(f, &stack_count, sizeof(hxa_uint32), file_name, silent))
|
|
return FALSE;
|
|
stack->layer_count = 0;
|
|
stack->layers = malloc((sizeof *stack->layers) * stack_count);
|
|
for(i = 0; i < stack_count; i++)
|
|
{
|
|
if(!hxa_load_name(f, file_name, stack->layers[i].name, silent))
|
|
return FALSE;
|
|
|
|
if(!hxa_load_data(f, &stack->layers[i].components, sizeof(hxa_uint8), file_name, silent) ||
|
|
!hxa_load_data(f, &type, sizeof(hxa_uint8), file_name, silent))
|
|
return FALSE;
|
|
if(type >= HXA_LDT_COUNT)
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s has a layer with type %u. No such type is supported\n", file_name, (unsigned int)type);
|
|
return FALSE;
|
|
}
|
|
stack->layers[i].type = (unsigned int)type;
|
|
size = type_sizes[stack->layers[i].type] * stack->layers[i].components * length;
|
|
stack->layers[i].data.double_data = malloc(size);
|
|
stack->layer_count++;
|
|
if(!hxa_load_data(f, stack->layers[i].data.double_data, sizeof(hxa_uint8) * size, file_name, silent))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
HXAFile *hxa_load(char *file_name, int silent)
|
|
{
|
|
FILE *f;
|
|
HXAFile *file;
|
|
HXANode *node;
|
|
unsigned int i, dimentions;
|
|
hxa_uint32 magic_number, node_count, version;
|
|
hxa_uint8 node_type;
|
|
size_t size;
|
|
f = fopen(file_name, "rb");
|
|
if(f == NULL)
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s could not be open for reading\n", file_name);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_data(f, &magic_number, sizeof(hxa_uint32), file_name, silent))
|
|
return NULL;
|
|
if(magic_number != (*(hxa_uint32 *)"HxA"))
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s is not a HxA file (incorrect magic number)\n", file_name);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_data(f, &version, sizeof(hxa_uint32), file_name, silent))
|
|
return NULL;
|
|
file = malloc(sizeof *file);
|
|
file->version = version;
|
|
file->node_count = 0;
|
|
file->node_array = NULL;
|
|
if(!hxa_load_data(f, &node_count, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
file->node_array = node = malloc((sizeof *file->node_array) * node_count);
|
|
for(i = 0; i < node_count; i++)
|
|
{
|
|
if(!hxa_load_data(f, &node_type, sizeof(hxa_uint8), file_name, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
node[i].type = node_type;
|
|
if(node[i].type >= HXA_NT_COUNT)
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s has a node of type %u\n", file_name, (unsigned int)node[i].type);
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
file->node_count++;
|
|
node[i].meta_data_count = 0;
|
|
switch(node[i].type)
|
|
{
|
|
case HXA_NT_GEOMETRY :
|
|
node[i].content.geometry.vertex_count = 0;
|
|
node[i].content.geometry.edge_corner_count = 0;
|
|
node[i].content.geometry.face_count = 0;
|
|
node[i].content.geometry.vertex_stack.layer_count = 0;
|
|
node[i].content.geometry.corner_stack.layer_count = 0;
|
|
node[i].content.geometry.edge_stack.layer_count = 0;
|
|
node[i].content.geometry.face_stack.layer_count = 0;
|
|
break;
|
|
case HXA_NT_IMAGE :
|
|
node[i].content.image.type = HXA_IT_CUBE_IMAGE;
|
|
node[i].content.image.resolution[0] = node[i].content.image.resolution[1] = node[i].content.image.resolution[2] = 1;
|
|
node[i].content.image.image_stack.layer_count = 0;
|
|
break;
|
|
}
|
|
if(!hxa_load_data(f, &node[i].meta_data_count, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_meta(f, file_name, &node[i].meta_data, &node[i].meta_data_count, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
|
|
switch(node[i].type)
|
|
{
|
|
case HXA_NT_GEOMETRY :
|
|
|
|
if(!hxa_load_data(f, &node[i].content.geometry.vertex_count, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s unexpectedly ended\n", file_name);
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_layer_stack(f, file_name, &node[i].content.geometry.vertex_stack, node[i].content.geometry.vertex_count, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_data(f, &node[i].content.geometry.edge_corner_count, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_layer_stack(f, file_name, &node[i].content.geometry.corner_stack, node[i].content.geometry.edge_corner_count, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(file->version > 2)
|
|
{
|
|
if(!hxa_load_layer_stack(f, file_name, &node[i].content.geometry.edge_stack, node[i].content.geometry.edge_corner_count, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
}
|
|
if(!hxa_load_data(f, &node[i].content.geometry.face_count, sizeof(hxa_uint32), file_name, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
if(!hxa_load_layer_stack(f, file_name, &node[i].content.geometry.face_stack, node[i].content.geometry.face_count, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case HXA_NT_IMAGE :
|
|
if(!hxa_load_data(f, &node[i].content.image.type, sizeof(hxa_uint8), file_name, silent))
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s unexpectedly ended\n", file_name);
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
dimentions = node[i].content.image.type;
|
|
if(node[i].content.image.type == HXA_IT_CUBE_IMAGE)
|
|
dimentions = 2;
|
|
node[i].content.image.resolution[0] = node[i].content.image.resolution[1] = node[i].content.image.resolution[2] = 1;
|
|
if(!hxa_load_data(f, &node[i].content.image.resolution, sizeof(hxa_uint32) * dimentions, file_name, silent))
|
|
{
|
|
if(!silent)
|
|
printf("HXA Error: File %s unexpectedly ended\n", file_name);
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
size = node[i].content.image.resolution[0] * node[i].content.image.resolution[1] * node[i].content.image.resolution[2];
|
|
if(node[i].content.image.type == HXA_IT_CUBE_IMAGE)
|
|
size *= 6;
|
|
if(!hxa_load_layer_stack(f, file_name, &node[i].content.image.image_stack, size, silent))
|
|
{
|
|
hxa_util_free_file(file);
|
|
return NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
fclose(f);
|
|
return file;
|
|
}
|
|
|
|
|
|
|
|
void hxa_save_meta(FILE *f, HXAMeta *meta, hxa_uint32 count)
|
|
{
|
|
HXAMeta *m;
|
|
unsigned int i, j;
|
|
hxa_uint8 type, name_lenght;
|
|
for(i = 0; i < count; i++)
|
|
{
|
|
for(j = 0; j < 255 && meta[i].name[j] != 0; j++);
|
|
name_lenght = j;
|
|
fwrite(&name_lenght, sizeof(hxa_uint8), 1, f);
|
|
fwrite(meta[i].name, sizeof(char), name_lenght, f);
|
|
type = meta[i].type;
|
|
fwrite(&type, sizeof(hxa_uint8), 1, f);
|
|
fwrite(&meta[i].array_length, sizeof(hxa_uint32), 1, f);
|
|
switch(meta[i].type)
|
|
{
|
|
case HXA_MDT_INT64 :
|
|
fwrite(meta[i].value.int64_value, sizeof(hxa_int64), meta[i].array_length, f);
|
|
break;
|
|
case HXA_MDT_DOUBLE :
|
|
fwrite(meta[i].value.double_value, sizeof(double), meta[i].array_length, f);
|
|
break;
|
|
case HXA_MDT_NODE :
|
|
fwrite(meta[i].value.node_value, sizeof(hxa_uint32), meta[i].array_length, f);
|
|
break;
|
|
case HXA_MDT_TEXT :
|
|
fwrite(meta[i].value.text_value, sizeof(char), meta[i].array_length, f);
|
|
break;
|
|
case HXA_MDT_BINARY :
|
|
fwrite(meta[i].value.bin_value, sizeof(char), meta[i].array_length, f);
|
|
break;
|
|
case HXA_MDT_META :
|
|
hxa_save_meta(f, meta[i].value.array_of_meta, meta[i].array_length);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void hxa_save_layer_stack(FILE *f, HXALayerStack *stack, unsigned int length)
|
|
{
|
|
const type_sizes[] = {sizeof(hxa_uint8), sizeof(hxa_uint32), sizeof(float), sizeof(double)};
|
|
unsigned int i, j;
|
|
hxa_uint8 name_lenght, type;
|
|
size_t size;
|
|
fwrite(&stack->layer_count, sizeof(hxa_uint32), 1, f);
|
|
for(i = 0; i < stack->layer_count; i++)
|
|
{
|
|
for(j = 0; j < 255 && stack->layers[i].name[j] != 0; j++);
|
|
name_lenght = j;
|
|
fwrite(&name_lenght, sizeof(hxa_uint8), 1, f);
|
|
fwrite(stack->layers[i].name, sizeof(hxa_uint8), name_lenght, f);
|
|
fwrite(&stack->layers[i].components, sizeof(hxa_uint8), 1, f);
|
|
type = stack->layers[i].type;
|
|
fwrite(&type, sizeof(hxa_uint8), 1, f);
|
|
size = stack->layers[i].components * length;
|
|
fwrite(stack->layers[i].data.double_data, type_sizes[stack->layers[i].type], size, f);
|
|
}
|
|
}
|
|
|
|
int hxa_save(char *file_name, HXAFile *data)
|
|
{
|
|
FILE *f;
|
|
HXANode *node;
|
|
hxa_uint8 type;
|
|
hxa_uint32 version;
|
|
unsigned int i, size, dimentions;
|
|
f = fopen(file_name, "wb");
|
|
if(f == NULL)
|
|
return FALSE;
|
|
fwrite("HxA", 4, 1, f);
|
|
version = HXA_VERSION_FORMAT;
|
|
fwrite(&version, sizeof(hxa_uint32), 1, f);
|
|
fwrite(&data->node_count, sizeof(hxa_uint32), 1, f);
|
|
node = data->node_array;
|
|
for(i = 0; i < data->node_count; i++)
|
|
{
|
|
type = node->type;
|
|
fwrite(&type, sizeof(hxa_uint8), 1, f);
|
|
fwrite(&node->meta_data_count, sizeof(hxa_uint32), 1, f);
|
|
hxa_save_meta(f, node->meta_data, node->meta_data_count);
|
|
switch(node->type)
|
|
{
|
|
case HXA_NT_GEOMETRY :
|
|
fwrite(&node->content.geometry.vertex_count, sizeof(hxa_uint32), 1, f);
|
|
hxa_save_layer_stack(f, &node->content.geometry.vertex_stack, node->content.geometry.vertex_count);
|
|
fwrite(&node->content.geometry.edge_corner_count, sizeof(hxa_uint32), 1, f);
|
|
hxa_save_layer_stack(f, &node->content.geometry.corner_stack, node->content.geometry.edge_corner_count);
|
|
hxa_save_layer_stack(f, &node->content.geometry.edge_stack, node->content.geometry.edge_corner_count);
|
|
fwrite(&node->content.geometry.face_count, sizeof(hxa_uint32), 1, f);
|
|
hxa_save_layer_stack(f, &node->content.geometry.face_stack, node->content.geometry.face_count);
|
|
break;
|
|
case HXA_NT_IMAGE :
|
|
type = node->content.image.type;
|
|
fwrite(type, sizeof(hxa_uint8), 1, f);
|
|
dimentions = node->content.image.type;
|
|
if(node->content.image.type == HXA_IT_CUBE_IMAGE)
|
|
dimentions = 2;
|
|
fwrite(&node->content.image.resolution, sizeof(hxa_uint32), dimentions, f);
|
|
size = node->content.image.resolution[0] * node->content.image.resolution[1] * node->content.image.resolution[2];
|
|
if(node->content.image.type == HXA_IT_CUBE_IMAGE)
|
|
size *= 6;
|
|
hxa_save_layer_stack(f, &node->content.image.image_stack, size);
|
|
break;
|
|
}
|
|
node++;
|
|
}
|
|
fclose(f);
|
|
return TRUE;
|
|
} |