1
0
mirror of https://github.com/quelsolaar/HxA synced 2025-04-22 22:18:49 -04:00

Added FBX support

This commit is contained in:
quelsolaar 2020-01-11 01:01:23 +01:00 committed by GitHub
parent b7fda618f0
commit f161952c64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1507 additions and 74 deletions

2
hxa.h
View File

@ -53,6 +53,8 @@ All names are stored as a 8bit unsigned integer indicating the length of the nam
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.
*/
#include "forge.h"
#ifndef HAX_INCLUDE
#define HAX_INCLUDE

292
hxa_fbx_convert.c Normal file
View File

@ -0,0 +1,292 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hxa.h"
#include "hxa_fbx_internal.h"
FBXRecord *hxa_fbx_convert_record_find(FBXRecord *record, char *name, unsigned int start, unsigned int prefix)
{
FBXRecord *child;
unsigned int i, j, k;
for(i = k = 0; i < record->used; i++)
{
child = &((FBXRecord *)record->children)[i];
// if(prefix)
// printf("child->name %s\n", child->name);
for(j = 0; name[j] != 0 && name[j] == child->name[j]; j++);
if(name[j] == 0 && (prefix || child->name[j] == 0))
{
if(start == k++)
return child;
}
}
return NULL;
}
int hxa_fbx_convert_property_test(FBXRecord *record, char *property_name)
{
FBXProperty *p;
uint i, j;
for(i = 0; i < record->property_count; i++)
{
if(record->property[i].type == FBX_PROPERTY_TYPE_TEXT)
{
for(j = 0; property_name[j] != 0 && record->property[i].data.buffer->buffer.text[j] == property_name[j]; j++);
if(property_name[j] == record->property[i].data.buffer->buffer.text[j])
return TRUE;
}
}
return FALSE;
}
int hxa_fbx_convert_layer_read(FBXRecord *record, HXALayerStack *layer_stack, uint length)
{
char *index = "Index";
HXALayer *layer;
FBXProperty *p, *index_property = NULL;
FBXRecord *param;
uint i, j, k, l, type_size, data_size, vertex_range, components;
unsigned char *data = NULL, *temp_buff = NULL;
size_t type_sizes[HXA_LDT_COUNT] = {sizeof(unsigned char), sizeof(int), sizeof(float), sizeof(double)};
unsigned int fbx_type_convesion[FBX_PROPERTY_TYPE_COUNT] = {HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_BOOLEAN,
HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT8,
HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT16,
HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT32,
HXA_LDT_INT32, // FBX_PROPERTY_TYPE_INT64,
HXA_LDT_FLOAT, // FBX_PROPERTY_TYPE_FLOAT32,
HXA_LDT_DOUBLE, // FBX_PROPERTY_TYPE_FLOAT64,
HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_TEXT,
HXA_LDT_COUNT, // FBX_PROPERTY_TYPE_RAW,
HXA_LDT_COUNT}; // FBX_PROPERTY_TYPE_UNKNOWN,
param = hxa_fbx_convert_record_find(record, "ReferenceInformationType", 0, FALSE);
if(param != NULL && (hxa_fbx_convert_property_test(param, "IndexToDirect") || hxa_fbx_convert_property_test(param, "Index")))
{
printf("IndexToDirect/n");
for(i = 0; i < record->used && index_property == NULL; i++)
{
param = &((FBXRecord *)record->children)[i];
for(j = 0; j < param->property_count && index_property == NULL; j++)
{
if(param->property[j].array_length % length == 0)
{
if(param->property[j].type == FBX_PROPERTY_TYPE_INT8 ||
param->property[j].type == FBX_PROPERTY_TYPE_INT16 ||
param->property[j].type == FBX_PROPERTY_TYPE_INT32 ||
param->property[j].type == FBX_PROPERTY_TYPE_INT64)
{
for(k = 0; k < param->name[k] != 0; k++)
{
for(l = 0; index[l] != 0 && index[l] == param->name[k + l]; l++);
if(index[l] != 0)
{
index_property = &param->property[j];
vertex_range = 0;
if(index_property->type == FBX_PROPERTY_TYPE_INT8)
for(k = 0; k < index_property->array_length; k++)
if(vertex_range < ((char *)index_property->data.array)[k])
vertex_range = ((char *)index_property->data.array)[k];
if(index_property->type == FBX_PROPERTY_TYPE_INT16)
for(k = 0; k < index_property->array_length; k++)
if(vertex_range < ((short *)index_property->data.array)[k])
vertex_range = ((short *)index_property->data.array)[k];
if(index_property->type == FBX_PROPERTY_TYPE_INT32)
for(k = 0; k < index_property->array_length; k++)
if(vertex_range < ((int *)index_property->data.array)[k])
vertex_range = ((int *)index_property->data.array)[k];
if(index_property->type == FBX_PROPERTY_TYPE_INT64)
for(k = 0; k < index_property->array_length; k++)
if(vertex_range < ((long long *)index_property->data.array)[k])
vertex_range = ((long long *)index_property->data.array)[k];
vertex_range++;
break;
}
}
}
}
}
}
if(index_property == NULL)
return FALSE;
}else
vertex_range = length;
for(i = 0; data == NULL && i < record->used; i++)
{
param = &((FBXRecord *)record->children)[i];
for(j = 0; j < param->property_count; j++)
{
if(&param->property[j] != index_property &&
param->property[j].array_length >= vertex_range &&
fbx_type_convesion[param->property[j].type] != HXA_LDT_COUNT)
{
data_size = param->property[j].array_length;
data = param->property[j].data.array;
++layer_stack->layer_count;
layer_stack->layers = realloc(layer_stack->layers, (sizeof *layer_stack->layers) * layer_stack->layer_count);
layer = &layer_stack->layers[layer_stack->layer_count - 1];
for(k = 0; param->name[k] != 0; k++)
layer->name[k] = param->name[k];
layer->name[k] = 0;
if(layer->name[0] == 'U' && layer->name[1] == 'V')
k = 0;
layer->type = fbx_type_convesion[param->property[j].type];
type_size = type_sizes[layer->type];
if(index_property == NULL)
layer->components = param->property[j].array_length / length;
else
layer->components = param->property[j].array_length / vertex_range;
layer->data.uint8_data = malloc(type_size * length * layer->components);
if(param->property[j].type == FBX_PROPERTY_TYPE_INT8)
{
temp_buff = malloc((sizeof *temp_buff) * data_size);
for(k = 0; k < 0; k++)
temp_buff[k] = (int)((char *)param->property[j].data.array)[k];
}else if(param->property[j].type == FBX_PROPERTY_TYPE_INT16)
{
temp_buff = malloc((sizeof *temp_buff) * data_size);
for(k = 0; k < 0; k++)
temp_buff[k] = (int)((short *)param->property[j].data.array)[k];
}else if(param->property[j].type == FBX_PROPERTY_TYPE_INT64)
{
temp_buff = malloc((sizeof *temp_buff) * data_size);
for(k = 0; k < 0; k++)
temp_buff[k] = (int)((long long *)param->property[j].data.array)[k];
}
break;
}
}
}
if(data == NULL)
return FALSE;
if(index_property != NULL)
{
layer->data.uint8_data = malloc((sizeof *layer->data.uint8_data) * layer->components * length * type_size);
if(index_property->type == FBX_PROPERTY_TYPE_INT8)
for(k = 0; k < index_property->array_length; k++)
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);
if(index_property->type == FBX_PROPERTY_TYPE_INT16)
for(k = 0; k < index_property->array_length; k++)
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);
if(index_property->type == FBX_PROPERTY_TYPE_INT32)
for(k = 0; k < index_property->array_length; k++)
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);
if(index_property->type == FBX_PROPERTY_TYPE_INT64)
for(k = 0; k < index_property->array_length; k++)
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);
}else
memcpy(layer->data.uint8_data, data, type_size * length * layer->components);
if(temp_buff != NULL)
free(temp_buff);
return FALSE;
}
extern void fbx_record_print_small(FBXRecord *record, uint generation);
HXAFile *hxa_fbx_convert(FBXRecord *record, HXAFile *file)
{
FBXRecord *object, *geometry, *vertices, *polygonvertexindex, *layer, *param;
HXALayerStack *stack;
HXANode *node;
unsigned int i, j, k, *ref, array_length;
object = hxa_fbx_convert_record_find(record, "Objects", 0, FALSE);
if(object == NULL)
return NULL;
if(file == NULL)
{
file = malloc(sizeof *file);
file->version = HXA_VERSION_FORMAT;
file->node_count = 0;
file->node_array = NULL;
}
for(i = 0; (geometry = hxa_fbx_convert_record_find(object, "Geometry", i, FALSE)) != NULL; i++)
{
fbx_record_print(geometry, 1);
vertices = hxa_fbx_convert_record_find(geometry, "Vertices", 0, FALSE);
polygonvertexindex = hxa_fbx_convert_record_find(geometry, "PolygonVertexIndex", 0, FALSE);
if(vertices != NULL && polygonvertexindex != NULL)
{
file->node_array = realloc(file->node_array, (sizeof *file->node_array) * ++file->node_count);
node = &file->node_array[file->node_count - 1];
node->meta_data_count = 0;
node->meta_data = NULL;
node->type = HXA_NT_GEOMETRY;
node->content.geometry.vertex_stack.layer_count = 1;
node->content.geometry.vertex_stack.layers = malloc(sizeof *node->content.geometry.vertex_stack.layers);
node->content.geometry.vertex_stack.layers->components = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS;
node->content.geometry.vertex_count = vertices->property->array_length / 3;
sprintf(node->content.geometry.vertex_stack.layers->name, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME);
if(vertices->property->type == FBX_PROPERTY_TYPE_FLOAT32)
{
node->content.geometry.vertex_stack.layers->type = HXA_LDT_FLOAT;
node->content.geometry.vertex_stack.layers->data.float_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.float_data) * vertices->property->array_length);
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);
}
if(vertices->property->type == FBX_PROPERTY_TYPE_FLOAT64)
{
node->content.geometry.vertex_stack.layers->type = HXA_LDT_DOUBLE;
node->content.geometry.vertex_stack.layers->data.double_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.double_data) * vertices->property->array_length);
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);
}
node->content.geometry.corner_stack.layer_count = 1;
node->content.geometry.corner_stack.layers = malloc(sizeof *node->content.geometry.corner_stack.layers);
node->content.geometry.corner_stack.layers->data.int32_data = malloc((sizeof *node->content.geometry.vertex_stack.layers->data.int32_data) * polygonvertexindex->property->array_length);
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);
node->content.geometry.edge_corner_count = polygonvertexindex->property->array_length;
sprintf(node->content.geometry.corner_stack.layers->name, HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME);
node->content.geometry.corner_stack.layers->components = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS;
node->content.geometry.corner_stack.layers->type = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE;
node->content.geometry.edge_stack.layers = 0;
node->content.geometry.edge_stack.layer_count = 0;
node->content.geometry.face_stack.layers = 0;
node->content.geometry.face_stack.layer_count = 0;
node->content.geometry.face_count = 0;
for(j = 0; j < node->content.geometry.edge_corner_count; j++)
if(node->content.geometry.corner_stack.layers->data.int32_data[j] < 0)
node->content.geometry.face_count++;
j = 0;
for(layer = hxa_fbx_convert_record_find(geometry, "LayerElement", j++, TRUE); layer != NULL; layer = hxa_fbx_convert_record_find(geometry, "LayerElement", j++, TRUE))
{
printf("Layers found %u %s\n", j, layer->name);
ref = NULL;
param = hxa_fbx_convert_record_find(layer, "MappingInformationType", 0, FALSE);
if(param != NULL)
{
if(hxa_fbx_convert_property_test(param, "ByPolygonVertex")) // Corner layer
{
hxa_fbx_convert_layer_read(layer, &node->content.geometry.corner_stack, node->content.geometry.edge_corner_count);
}else if(hxa_fbx_convert_property_test(param, "ByVertice")) // Vertex Layer
{
hxa_fbx_convert_layer_read(layer, &node->content.geometry.vertex_stack, node->content.geometry.vertex_count);
}else if(hxa_fbx_convert_property_test(param, "ByPolygon")) // Polygon Layer
{
hxa_fbx_convert_layer_read(layer, &node->content.geometry.face_stack, node->content.geometry.face_count);
}else if(hxa_fbx_convert_property_test(param, "ByEdge")) // EdgeLayer
{
hxa_fbx_convert_layer_read(layer, &node->content.geometry.edge_stack, node->content.geometry.edge_corner_count);
}
}
}
j = 0;
}
}
return file;
}

61
hxa_fbx_internal.h Normal file
View File

@ -0,0 +1,61 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tinf.h"
typedef enum{
FBX_PROPERTY_TYPE_BOOLEAN,
FBX_PROPERTY_TYPE_INT8,
FBX_PROPERTY_TYPE_INT16,
FBX_PROPERTY_TYPE_INT32,
FBX_PROPERTY_TYPE_INT64,
FBX_PROPERTY_TYPE_FLOAT32,
FBX_PROPERTY_TYPE_FLOAT64,
FBX_PROPERTY_TYPE_TEXT,
FBX_PROPERTY_TYPE_RAW,
FBX_PROPERTY_TYPE_UNKNOWN,
FBX_PROPERTY_TYPE_COUNT
}FBXPropertyType;
extern const unsigned int fbx_property_size[FBX_PROPERTY_TYPE_COUNT];
typedef struct{
unsigned int length;
union{
unsigned char raw[1];
char text[1];
}buffer;
}FBXBuffer;
typedef struct{
FBXPropertyType type;
unsigned int array_length;
union{
char boolean_type;
char int8_type;
short int16_type;
unsigned int int32_type;
long long int64_type;
float float32_type;
double float64_type;
void *array;
FBXBuffer *buffer;
}data;
}FBXProperty;
typedef struct{
unsigned long long end_ofset;
unsigned long long property_count;
unsigned long long property_list_length;
unsigned char name_length;
char name[256];
FBXProperty *property;
void *children;
unsigned int allocated;
unsigned int used;
}FBXRecord;
extern HXAFile *hxa_fbx_convert(FBXRecord *record, HXAFile *file);
extern void fbx_record_print(FBXRecord *record, uint generation);
extern void fbx_record_print_small(FBXRecord *record, uint generation);

673
hxa_fbx_parse.c Normal file
View File

@ -0,0 +1,673 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hxa.h"
#include "hxa_fbx_internal.h"
extern int hxa_inflate(unsigned char *output, size_t *output_length, unsigned char *input, size_t input_length);
const unsigned int fbx_property_size[FBX_PROPERTY_TYPE_COUNT] = {sizeof(char), // FBX_PROPERTY_TYPE_BOOLEAN
sizeof(char), // FBX_PROPERTY_TYPE_INT8
sizeof(short), // FBX_PROPERTY_TYPE_INT16
sizeof(int), // FBX_PROPERTY_TYPE_INT32
sizeof(long long), // FBX_PROPERTY_TYPE_INT64
sizeof(float), // FBX_PROPERTY_TYPE_FLOAT32
sizeof(double), // FBX_PROPERTY_TYPE_FLOAT64
sizeof(char), // FBX_PROPERTY_TYPE_TEXT
sizeof(unsigned char), // FBX_PROPERTY_TYPE_RAW
0}; // FBX_PROPERTY_TYPE_UNKNOWN
const uint fbx_property_code[256] = {FBX_PROPERTY_TYPE_UNKNOWN, /* NULL */
FBX_PROPERTY_TYPE_UNKNOWN, /* Start of header */
FBX_PROPERTY_TYPE_UNKNOWN, /* Start of text */
FBX_PROPERTY_TYPE_UNKNOWN, /* End of text */
FBX_PROPERTY_TYPE_UNKNOWN, /* End of transmission */
FBX_PROPERTY_TYPE_UNKNOWN, /* Enquiry */
FBX_PROPERTY_TYPE_UNKNOWN, /* Acknowledgment */
FBX_PROPERTY_TYPE_UNKNOWN, /* Bell */
FBX_PROPERTY_TYPE_UNKNOWN, /* Backspace */
FBX_PROPERTY_TYPE_UNKNOWN, /* Horizontal Tab */
FBX_PROPERTY_TYPE_UNKNOWN, /* Line feed */
FBX_PROPERTY_TYPE_UNKNOWN, /* Vertical tab */
FBX_PROPERTY_TYPE_UNKNOWN, /* Form feed */
FBX_PROPERTY_TYPE_UNKNOWN, /* Carriage return */
FBX_PROPERTY_TYPE_UNKNOWN, /* Shift out */
FBX_PROPERTY_TYPE_UNKNOWN, /* Shift in */
FBX_PROPERTY_TYPE_UNKNOWN, /* Data Link Escape */
FBX_PROPERTY_TYPE_UNKNOWN, /* Device control 1 */
FBX_PROPERTY_TYPE_UNKNOWN, /* Device control 2 */
FBX_PROPERTY_TYPE_UNKNOWN, /* Device control 3 */
FBX_PROPERTY_TYPE_UNKNOWN, /* Device control 4 */
FBX_PROPERTY_TYPE_UNKNOWN, /* Negative Acknowledgment */
FBX_PROPERTY_TYPE_UNKNOWN, /* Syncronus idle */
FBX_PROPERTY_TYPE_UNKNOWN, /* End of transmission block */
FBX_PROPERTY_TYPE_UNKNOWN, /* Cansel */
FBX_PROPERTY_TYPE_UNKNOWN, /* End of medium */
FBX_PROPERTY_TYPE_UNKNOWN, /* Substitute */
FBX_PROPERTY_TYPE_UNKNOWN, /* Ecscape */
FBX_PROPERTY_TYPE_UNKNOWN, /* File separator */
FBX_PROPERTY_TYPE_UNKNOWN, /* Group separator */
FBX_PROPERTY_TYPE_UNKNOWN, /* Record separator */
FBX_PROPERTY_TYPE_UNKNOWN, /* Unit separator */
FBX_PROPERTY_TYPE_UNKNOWN, /* Space */
FBX_PROPERTY_TYPE_UNKNOWN, /* ! */
FBX_PROPERTY_TYPE_UNKNOWN, /* " */
FBX_PROPERTY_TYPE_UNKNOWN, /* # */
FBX_PROPERTY_TYPE_UNKNOWN, /* $ */
FBX_PROPERTY_TYPE_UNKNOWN, /* % */
FBX_PROPERTY_TYPE_UNKNOWN, /* & */
FBX_PROPERTY_TYPE_UNKNOWN, /* ' */
FBX_PROPERTY_TYPE_UNKNOWN, /* ( */
FBX_PROPERTY_TYPE_UNKNOWN, /* ) */
FBX_PROPERTY_TYPE_UNKNOWN, /* * */
FBX_PROPERTY_TYPE_UNKNOWN, /* + */
FBX_PROPERTY_TYPE_UNKNOWN, /* , */
FBX_PROPERTY_TYPE_UNKNOWN, /* - */
FBX_PROPERTY_TYPE_UNKNOWN, /* . */
FBX_PROPERTY_TYPE_UNKNOWN, /* / */
FBX_PROPERTY_TYPE_UNKNOWN, /* 0 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 1 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 2 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 3 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 4 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 5 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 6 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 7 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 8 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 9 */
FBX_PROPERTY_TYPE_UNKNOWN, /* : */
FBX_PROPERTY_TYPE_UNKNOWN, /* ; */
FBX_PROPERTY_TYPE_UNKNOWN, /* < */
FBX_PROPERTY_TYPE_UNKNOWN, /* = */
FBX_PROPERTY_TYPE_UNKNOWN, /* > */
FBX_PROPERTY_TYPE_UNKNOWN, /* ? */
FBX_PROPERTY_TYPE_UNKNOWN, /* @ */
FBX_PROPERTY_TYPE_UNKNOWN, /* A */
FBX_PROPERTY_TYPE_UNKNOWN, /* B */
FBX_PROPERTY_TYPE_BOOLEAN, /* C */
FBX_PROPERTY_TYPE_FLOAT64, /* D */
FBX_PROPERTY_TYPE_UNKNOWN, /* E */
FBX_PROPERTY_TYPE_FLOAT32, /* F */
FBX_PROPERTY_TYPE_UNKNOWN, /* G */
FBX_PROPERTY_TYPE_UNKNOWN, /* H */
FBX_PROPERTY_TYPE_INT32, /* I */
FBX_PROPERTY_TYPE_UNKNOWN, /* J */
FBX_PROPERTY_TYPE_UNKNOWN, /* K */
FBX_PROPERTY_TYPE_INT64, /* L */
FBX_PROPERTY_TYPE_UNKNOWN, /* M */
FBX_PROPERTY_TYPE_UNKNOWN, /* N */
FBX_PROPERTY_TYPE_UNKNOWN, /* O */
FBX_PROPERTY_TYPE_UNKNOWN, /* P */
FBX_PROPERTY_TYPE_UNKNOWN, /* Q */
FBX_PROPERTY_TYPE_RAW, /* R */
FBX_PROPERTY_TYPE_TEXT, /* S */
FBX_PROPERTY_TYPE_UNKNOWN, /* T */
FBX_PROPERTY_TYPE_UNKNOWN, /* U */
FBX_PROPERTY_TYPE_UNKNOWN, /* V */
FBX_PROPERTY_TYPE_UNKNOWN, /* W */
FBX_PROPERTY_TYPE_UNKNOWN, /* X */
FBX_PROPERTY_TYPE_INT16, /* Y */
FBX_PROPERTY_TYPE_UNKNOWN, /* Z */
FBX_PROPERTY_TYPE_UNKNOWN, /* [ */
FBX_PROPERTY_TYPE_UNKNOWN, /* \ */
FBX_PROPERTY_TYPE_UNKNOWN, /* ] */
FBX_PROPERTY_TYPE_UNKNOWN, /* ^ */
FBX_PROPERTY_TYPE_UNKNOWN, /* _ */
FBX_PROPERTY_TYPE_UNKNOWN, /* ` */
FBX_PROPERTY_TYPE_UNKNOWN, /* a */
FBX_PROPERTY_TYPE_BOOLEAN, /* b */
FBX_PROPERTY_TYPE_UNKNOWN, /* c */
FBX_PROPERTY_TYPE_FLOAT64, /* d */
FBX_PROPERTY_TYPE_UNKNOWN, /* e */
FBX_PROPERTY_TYPE_FLOAT32, /* f */
FBX_PROPERTY_TYPE_UNKNOWN, /* g */
FBX_PROPERTY_TYPE_UNKNOWN, /* h */
FBX_PROPERTY_TYPE_INT32, /* i */
FBX_PROPERTY_TYPE_UNKNOWN, /* j */
FBX_PROPERTY_TYPE_UNKNOWN, /* k */
FBX_PROPERTY_TYPE_INT64, /* l */
FBX_PROPERTY_TYPE_UNKNOWN, /* m */
FBX_PROPERTY_TYPE_UNKNOWN, /* n */
FBX_PROPERTY_TYPE_UNKNOWN, /* o */
FBX_PROPERTY_TYPE_UNKNOWN, /* p */
FBX_PROPERTY_TYPE_UNKNOWN, /* q */
FBX_PROPERTY_TYPE_UNKNOWN, /* r */
FBX_PROPERTY_TYPE_UNKNOWN, /* s */
FBX_PROPERTY_TYPE_UNKNOWN, /* t */
FBX_PROPERTY_TYPE_UNKNOWN, /* u */
FBX_PROPERTY_TYPE_UNKNOWN, /* v */
FBX_PROPERTY_TYPE_UNKNOWN, /* w */
FBX_PROPERTY_TYPE_UNKNOWN, /* x */
FBX_PROPERTY_TYPE_INT16, /* y */
FBX_PROPERTY_TYPE_UNKNOWN, /* z */
FBX_PROPERTY_TYPE_UNKNOWN, /* { */
FBX_PROPERTY_TYPE_UNKNOWN, /* | */
FBX_PROPERTY_TYPE_UNKNOWN, /* } */
FBX_PROPERTY_TYPE_UNKNOWN, /* ~ */
FBX_PROPERTY_TYPE_UNKNOWN, /* 127 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 128 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 129 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 130 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 131 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 132 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 133 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 134 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 135 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 136 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 137 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 138 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 139 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 140 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 141 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 142 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 143 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 144 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 145 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 146 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 147 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 148 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 149 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 150 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 151 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 152 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 153 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 154 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 155 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 156 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 157 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 158 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 159 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 160 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 161 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 162 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 163 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 164 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 165 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 166 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 167 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 168 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 169 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 170 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 171 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 172 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 173 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 174 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 175 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 176 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 177 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 178 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 179 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 180 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 181 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 182 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 183 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 184 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 185 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 186 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 187 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 188 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 189 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 190 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 191 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 192 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 193 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 194 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 195 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 196 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 197 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 198 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 199 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 200 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 201 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 202 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 203 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 204 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 205 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 206 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 207 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 208 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 209 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 210 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 211 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 212 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 213 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 214 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 215 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 216 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 217 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 218 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 219 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 220 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 221 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 222 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 223 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 224 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 225 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 226 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 227 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 228 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 229 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 230 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 231 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 232 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 233 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 234 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 235 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 236 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 237 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 238 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 239 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 240 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 241 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 242 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 243 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 244 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 245 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 246 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 247 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 248 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 249 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 250 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 251 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 252 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 253 */
FBX_PROPERTY_TYPE_UNKNOWN, /* 254 */
FBX_PROPERTY_TYPE_UNKNOWN}; /* 255 */
static const union { uint8 bytes[4]; uint32 value; } forge_host_order = {{0, 1, 2, 3}};
void fbx_unpack_uint64_big(uint64 *output, uint8 *input)
{
uint64 data;
data = ((uint64) input[3]) << 56;
data |= ((uint64) input[2]) << 48;
data |= ((uint64) input[1]) << 40;
data |= ((uint64) input[0]) << 32;
data |= ((uint64) input[7]) << 24;
data |= ((uint64) input[6]) << 16;
data |= ((uint64) input[5]) << 8;
data |= (uint64) input[4];
*output = data;
}
void fbx_unpack_uint32_big(uint32 *output, uint8 *input)
{
uint32 data;
data = ((uint32) input[3]) << 24;
data |= ((uint32) input[2]) << 16;
data |= ((uint32) input[1]) << 8;
data |= (uint32) input[0];
*output = data;
}
void fbx_unpack_uint16_big(uint16 *output, uint8 *input)
{
uint16 data;
data |= ((uint16) input[1]) << 8;
data |= (uint16) input[0];
*output = data;
}
#if _M_IX86 || _M_X64 || __x86_64__ || __i386 ||_X86_ || _X86_ || __INTEL__
#define FBX_LITTLE_ENDIAN
#else
#define FBX_UNKNOWN_ENDIAN
#endif
#ifdef FBX_LITTLE_ENDIAN
#define fbx_unpack_uint16(a, b) memcpy(a, b, sizeof(uint16))
#define fbx_unpack_uint32(a, b) memcpy(a, b, sizeof(uint32))
#define fbx_unpack_uint64(a, b) memcpy(a, b, sizeof(uint64))
#else
#define fbx_unpack_uint16 fbx_unpack_uint16_big
#define fbx_unpack_uint32 fbx_unpack_uint32_big
#define fbx_unpack_uint64 fbx_unpack_uint64_big
#endif
void fbx_record_print(FBXRecord *record, uint generation)
{
void *array;
char tabs[64];
uint i, j;
for(i = 0; i < generation && i < 64 - 1; i++)
tabs[i] = ' ';
tabs[i] = 0;
printf("%send_ofset %u\n", tabs, record->end_ofset);
printf("%sproperty_count %u\n", tabs, record->property_count);
printf("%sproperty_list_length %u\n", tabs, record->property_list_length);
printf("%sname_length %u\n", tabs, (uint)record->name_length);
printf("%sname %s\n", tabs, record->name);
for(i = 0; i < record->property_count; i++)
{
printf("%sproperty[%u] type %u\n", tabs, i, record->property[i].type);
if(record->property[i].array_length > 1)
printf("%sproperty[%u] array_length %u\n", tabs, i, record->property[i].array_length);
if(record->property[i].array_length == 1)
array = &record->property[i].data.boolean_type;
else
array = record->property[i].data.array;
printf("%sproperty[%u] value =", tabs, i);
switch(record->property[i].type)
{
case FBX_PROPERTY_TYPE_BOOLEAN :
for(j = 0; j < record->property[i].array_length; j++)
{
if(record->property[i].data.boolean_type)
printf(" TRUE");
else
printf(" FALSE");
}
break;
case FBX_PROPERTY_TYPE_INT8 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int8 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT16 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int16 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT32 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int32 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT64 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int64 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_FLOAT32 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %f", (float)(((float *)array)[j]));
break;
case FBX_PROPERTY_TYPE_FLOAT64 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %f", (float)(((double *)array)[j]));
break;
case FBX_PROPERTY_TYPE_TEXT :
printf(" \"%s\"", record->property[i].data.buffer->buffer.text);
break;
case FBX_PROPERTY_TYPE_RAW :
printf(" RAW");
break;
case FBX_PROPERTY_TYPE_UNKNOWN :
printf(" UNKNOWN");
break;
}
printf("\n");
}
for(i = 0; i < record->used; i++)
fbx_record_print(&((FBXRecord *)record->children)[i], generation + 1);
}
void fbx_record_print_small(FBXRecord *record, uint generation)
{
void *array;
uint i, j;
for(i = 0; i < generation; i++)
printf(" ");
printf("name %s = ", record->name);
for(i = 0; i < record->property_count; i++)
{
if(record->property[i].array_length == 1)
array = &record->property[i].data.boolean_type;
else
array = record->property[i].data.array;
if(i != 0)
printf(",");
switch(record->property[i].type)
{
case FBX_PROPERTY_TYPE_BOOLEAN :
for(j = 0; j < record->property[i].array_length; j++)
{
if(record->property[i].data.boolean_type)
printf(" TRUE");
else
printf(" FALSE");
}
break;
case FBX_PROPERTY_TYPE_INT8 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int8 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT16 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int16 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT32 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int32 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_INT64 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %i", (int)(((int64 *)array)[j]));
break;
case FBX_PROPERTY_TYPE_FLOAT32 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %f", (float)(((float *)array)[j]));
break;
case FBX_PROPERTY_TYPE_FLOAT64 :
for(j = 0; j < record->property[i].array_length; j++)
printf(" %f", (float)(((double *)array)[j]));
break;
case FBX_PROPERTY_TYPE_TEXT :
printf(" \"%s\"", record->property[i].data.buffer->buffer.text);
break;
case FBX_PROPERTY_TYPE_RAW :
printf(" RAW");
break;
case FBX_PROPERTY_TYPE_UNKNOWN :
printf(" UNKNOWN");
break;
}
}
printf("\n");
// for(i = 0; i < record->used; i++)
// fbx_record_print_small(&((FBXRecord *)record->children)[i], generation + 1);
}
/*
data[51] = 18 - Device control 2
data[52] = 70 - F - "FBXHeaderExtensiont"
*/
uint fbx_load_record(FBXRecord *record, uint8 *data, uint read_pos, uint version)
{
uint i, j, k, type, encoding, compressed_length;
uint32 read32;
uint8 *array;
uint8 *write, *read;
record->allocated = 0;
record->used = 0;
record->children = 0;
if(version < 7500)
{
fbx_unpack_uint32(&read32, &data[read_pos + 0]);
record->end_ofset = (uint64)read32;
fbx_unpack_uint32(&read32, &data[read_pos + 4]);
record->property_count = (uint64)read32;
fbx_unpack_uint32(&read32, &data[read_pos + 8]);
record->property_list_length = (uint64)read32;
record->name_length = data[read_pos + 12];
for(i = 0; i < record->name_length; i++)
record->name[i] = data[read_pos + 13 + i];
record->name[i] = 0;
i += 13;
}else
{
fbx_unpack_uint64(&record->end_ofset, &data[read_pos + 0]);
fbx_unpack_uint64(&record->property_count, &data[read_pos + 8]);
fbx_unpack_uint64(&record->property_list_length, &data[read_pos + 16]);
record->name_length = data[read_pos + 24];
for(i = 0; i < record->name_length; i++)
record->name[i] = data[read_pos + 25 + i];
record->name[i] = 0;
i += 25;
}
if(record->property_list_length > 100000)
{
// f_print_raw(data, 2000);
record->property_list_length = 0;
exit(0);
}
// if(record->property_list_length != 0)
// f_print_raw(&data[i], record->property_list_length);
if(record->property_count != 0)
{
record->property = malloc((sizeof *record->property) * record->property_count);
for(j = 0; j < record->property_count; j++)
{
record->property[j].type = fbx_property_code[data[read_pos + i]];
// if(record->property[j].type == FBX_PROPERTY_TYPE_FLOAT64)
// printf("type %u %u %u\n", record->property[j].type, (uint)data[i], i);
if(data[read_pos + i] > 'Z')
{
fbx_unpack_uint32(&record->property[j].array_length, &data[read_pos + i + 1]);
fbx_unpack_uint32(&encoding, &data[read_pos + i + 5]);
fbx_unpack_uint32(&compressed_length, &data[read_pos + i + 9]);
i += 1 + sizeof(uint32) * 3;
record->property[j].data.array = malloc(fbx_property_size[record->property[j].type] * record->property[j].array_length);
if(compressed_length != 0 && encoding != 0)
{
uint output_length;
output_length = compressed_length * 4;
tinf_init();
k = 0;
while(TRUE)
{
/* uint8 *test;
test = malloc(fbx_property_size[record->property[j].type] * record->property[j].array_length);
hxa_inflate(test, &output_length, &data[read_pos + i + 2], compressed_length);
if(TINF_OK == tinf_uncompress(record->property[j].data.array, &output_length, &data[read_pos + i + 2], compressed_length))
{
uint ii;
for(ii = 0; ii < output_length; ii++)
if(((uint8 *)record->property[j].data.array)[ii] != test[ii])
ii++;
break;
}*/
if(hxa_inflate(record->property[j].data.array, &output_length, &data[read_pos + i + 2], compressed_length))
break;
i++;
k++;
}
i += compressed_length;
#ifdef FBX_LITTLE_ENDIAN
read = write = NULL;
#else
read = record->property[j].data.array;
write = record->property[j].data.array;
#endif
}else
{
read = &data[read_pos + i];
write = record->property[j].data.array;
i += fbx_property_size[record->property[j].type] * record->property[j].array_length;
}
}else
{
record->property[j].array_length = 1;
i++;
if(record->property[j].type == FBX_PROPERTY_TYPE_TEXT ||
record->property[j].type == FBX_PROPERTY_TYPE_RAW)
{
uint32 length;
fbx_unpack_uint32(&length, &data[read_pos + i]);
i += sizeof(uint32);
record->property[j].data.buffer = malloc(sizeof(uint32) + length + 1);
record->property[j].data.buffer->length = length;
memcpy(record->property[j].data.buffer->buffer.raw, &data[read_pos + i], length);
record->property[j].data.buffer->buffer.raw[length] = 0;
i += length;
read = write = NULL;
}else
{
write = &record->property[j].data;
read = &data[read_pos + i];
i += fbx_property_size[record->property[j].type];
}
}
if(write != NULL)
{
#ifdef FBX_LITTLE_ENDIAN
memcpy(write, read, fbx_property_size[record->property[j].type] * record->property[j].array_length);
#else
switch(fbx_property_size[record->property[j].type])
{
case 1 :
memcpy(write, read, record->property[j].array_length);
break;
case 2 :
for(k = 0; k < record->property[j].array_length; k++)
fbx_unpack_uint16((uint16 *)&write[k * sizeof(int16)], &read[k * sizeof(int16)]);
break;
case 4 :
for(k = 0; k < record->property[j].array_length; k++)
fbx_unpack_uint32((uint16 *)&write[k * sizeof(int32)], &read[k * sizeof(int32)]);
break;
case 8 :
for(k = 0; k < record->property[j].array_length; k++)
fbx_unpack_uint64((uint64 *)&write[k * sizeof(int64)], &read[k * sizeof(int64)]);
break;
}
#endif
}
}
}else
record->property = NULL;
read_pos += i;
while(read_pos < record->end_ofset)
{
if(record->used == record->allocated)
{
record->allocated += 16;
record->children = realloc(record->children, sizeof(FBXRecord) * record->allocated);
}
read_pos = fbx_load_record(&((FBXRecord *)record->children)[record->used++], data, read_pos, version);
}
return read_pos;
}
HXAFile *hxa_fbx_load(char *file_name, HXAFile *hxa_file)
{
uint levels[1024], level_end[1024];
FBXRecord record;
uint32 version = 0;
size_t size, i;
uint8 *file;
// freopen("output.txt", "w", stdout);
// setbuf(stdout, NULL);
file = f_text_load(file_name, &size);
if(file == NULL)
return NULL;
record.end_ofset = size;
record.property_count = 0;
record.property_list_length = 0;
record.name_length = 0;
record.name[0] = 0;
record.property = NULL;
record.children = NULL;
record.allocated = 0;
record.used = 0;
if(file == NULL)
return NULL;
fbx_unpack_uint32(&version, &file[23]);
i = 27;
while(i < record.end_ofset - 1000)
{
if(record.used == record.allocated)
{
record.allocated += 16;
record.children = realloc(record.children, sizeof(FBXRecord) * record.allocated);
}
i = fbx_load_record(&((FBXRecord *)record.children)[record.used++], file, i, version);
}
for(i = 0; i < record.used; i++)
fbx_record_print_small(&((FBXRecord *)record.children)[i], 0);
hxa_file = hxa_fbx_convert(&record, hxa_file);
free(file);
return hxa_file;
}

View File

@ -1,3 +1,8 @@
#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"
@ -157,13 +162,14 @@ int hxa_load_meta(FILE *f, char *file_name, HXAMeta **meta, hxa_uint32 *count, i
return FALSE;
break;
case HXA_MDT_TEXT :
m->value.text_value = malloc(sizeof(char) * (m->array_length + 1));
if(!hxa_load_data(f, m->value.node_value, sizeof(hxa_uint32) * m->array_length, file_name, silent))
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.text_value = malloc(sizeof(char) * (m->array_length + 1));
if(!hxa_load_data(f, m->value.node_value, sizeof(hxa_uint32) * m->array_length, file_name, silent))
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 :

View File

@ -77,19 +77,19 @@ float un_hole_edge_rate(int *ref, float *vertex, unsigned int *neighbour, unsign
float n[3], n2[3], f, v0[3], v1[3];
unsigned int next;
int vr[4];
vr[0] = (hxa_ref(edge_a)) * 3;
vr[1] = (hxa_ref(edge_b)) * 3;
vr[2] = (hxa_ref(edge_c)) * 3;
vr[0] = (hxa_ref(ref, edge_a)) * 3;
vr[1] = (hxa_ref(ref, edge_b)) * 3;
vr[2] = (hxa_ref(ref, edge_c)) * 3;
un_hole_normal3f(n, &vertex[vr[1]], &vertex[vr[0]], &vertex[vr[2]]);
next = hxa_corner_get_previous(ref, edge_a);
vr[3] = (hxa_ref(next)) * 3;
vr[3] = (hxa_ref(ref, next)) * 3;
un_hole_normal3f(n2, &vertex[vr[0]], &vertex[vr[1]], &vertex[vr[3]]);
f = 1.0 + n[0] * n2[0] + n[1] * n2[1] + n[2] * n2[2];
if(f != f)
f = 0.1;
next = hxa_corner_get_previous(ref, edge_b);
vr[3] = (hxa_ref(next)) * 3;
vr[3] = (hxa_ref(ref, next)) * 3;
un_hole_normal3f(n2, &vertex[vr[1]], &vertex[vr[2]], &vertex[vr[3]]);
f *= 1.0 + n[0] * n2[0] + n[1] * n2[1] + n[2] * n2[2];
if(f != f)
@ -106,7 +106,6 @@ unsigned int hxa_hole_close_one(int *ref, unsigned int ref_length, float *vertex
{
HxAHoleEdge *start, *next, *found;
unsigned int i, count = 0;
float best;
i = edge;
while(1)
{
@ -132,23 +131,16 @@ unsigned int hxa_hole_close_one(int *ref, unsigned int ref_length, float *vertex
while(count != 0)
{
found = NULL;
next = start;
best = -1.0;
for(i = 0; i < count; i++)
{
if(best < next->value && ((HxAHoleEdge *)next->next)->value > 0.0001 || ((HxAHoleEdge *)next->previous)->value > 0.0001)
{
best = next->value;
found = next;
}
next = next->next;
}
found = start;
for(next = start->next; next != start; next = next->next)
if(found->value < next->value)
found = next;
next = found->next;
ref[ref_length + 0] = hxa_ref(found->edge);
ref[ref_length + 1] = hxa_ref(((HxAHoleEdge *)next->next)->edge);
ref[ref_length + 2] = -hxa_ref(next->edge) - 1;
ref[ref_length + 0] = hxa_ref(ref, found->edge);
ref[ref_length + 1] = hxa_ref(ref, ((HxAHoleEdge *)next->next)->edge);
ref[ref_length + 2] = -hxa_ref(ref, next->edge) - 1;
neighbour[ref_length + 1] = next->edge;
neighbour[ref_length + 2] = found->edge;
@ -172,7 +164,7 @@ unsigned int hxa_hole_close_one(int *ref, unsigned int ref_length, float *vertex
found->edge = ref_length;
found->value = un_hole_edge_rate(ref, vertex_array, neighbour, found->edge, ((HxAHoleEdge *)found->next)->edge, ((HxAHoleEdge *)((HxAHoleEdge *)found->next)->next)->edge);
((HxAHoleEdge *)found->previous)->value = un_hole_edge_rate(ref, vertex_array, neighbour, ((HxAHoleEdge *)found->previous)->edge, found->edge, ((HxAHoleEdge *)found->next)->edge);
if(un_hole_edge_length(ref, vertex_array, ref_length + 1) < un_hole_edge_length(ref, vertex_array, ref_length + 0))
if(un_hole_edge_length(ref, vertex_array, ref_length + 1) < un_hole_edge_length(ref, vertex_array, ref_length + 2))
found->value *= 0.95;
else
((HxAHoleEdge *)found->previous)->value *= 0.95;

View File

@ -20,13 +20,10 @@ int hxa_convert_param_to_int(char *string, unsigned int *output)
return TRUE;
}
extern void hxa_load_png(char *file_name);
int main(int argc, char **argv)
{
HXAFile *file, *file2;
unsigned int i, j, silent, save, int_param;
hxa_load_png("import_test.png");
if(argc < 2)
{
printf("HxA utility. Written by Eskil Steenberg www.quelsolaar.com. MIT License\n");
@ -53,7 +50,9 @@ int main(int argc, char **argv)
printf("Loading HxA file: %s\n", argv[1]);
file = hxa_load(argv[1], silent);
if(file == NULL)
{
file = hxa_fbx_load(argv[1], file);
if(file == NULL)
{
if(!silent)
printf("HxA Error: Loading file failed. Exiting...\n");
return FALSE;

63
hxa_util_gpu_optimize.c Normal file
View File

@ -0,0 +1,63 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
void hxa_corner_to_vertex(HXANode *node)
{
size_t type_sizes[HXA_LDT_COUNT] = {sizeof(unsigned char), sizeof(int), sizeof(float), sizeof(double)};
int *new_ref, *old_ref, vertex_count;
unsigned int i, j, *vertex_ref, section;
unsigned char *read, *write;
if(node->content.geometry.corner_stack.layer_count == 1)
return;
new_ref = malloc((sizeof *new_ref) * node->content.geometry.edge_corner_count);
vertex_ref = malloc((sizeof *vertex_ref) * node->content.geometry.edge_corner_count);
old_ref = node->content.geometry.corner_stack.layers->data.int32_data;
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
{
vertex_ref[i] = -1;
new_ref[i] = -1;
}
for(i = vertex_count = 0; i < node->content.geometry.edge_corner_count; i++)
{
if(new_ref[i] == -1)
{
if(old_ref[i] < 0)
new_ref[i] = -1 - vertex_count;
else
new_ref[i] = vertex_count;
vertex_ref[vertex_count++] = i;
}
}
for(i = 0; i < node->content.geometry.vertex_stack.layer_count; i++)
{
section = node->content.geometry.vertex_stack.layers[i].components * type_sizes[node->content.geometry.vertex_stack.layers[i].type];
write = malloc(section * vertex_count);
read = node->content.geometry.vertex_stack.layers[i].data.uint8_data;
for(j = 0; j < vertex_count; j++)
memcpy(&write[j * section], &read[old_ref[vertex_ref[j]] * section], section);
free(read);
node->content.geometry.vertex_stack.layers[i].data.uint8_data = write;
}
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));
for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++)
{
node->content.geometry.vertex_stack.layers[node->content.geometry.vertex_stack.layer_count] = node->content.geometry.corner_stack.layers[i];
section = node->content.geometry.corner_stack.layers[i].components * type_sizes[node->content.geometry.corner_stack.layers[i].type];
write = malloc(section * vertex_count);
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;
for(j = 0; j < vertex_count; j++)
memcpy(&write[j * section], &read[vertex_ref[j] * section], section);
}
for(i = 0; i < node->content.geometry.corner_stack.layer_count; i++)
free(node->content.geometry.corner_stack.layers[i].data.uint8_data);
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.layers->data.int32_data = new_ref;
}

View File

@ -12,13 +12,12 @@ typedef struct{
unsigned int hxa_inflate_read_bits(HxAInflateBitStream *stream, unsigned int bits)
{
unsigned int output, progress;
output = *stream->stream << stream->bit;
for(progress = 8 - stream->bit; progress < bits && stream->stream <= stream->end; progress += 8)
{
output += *stream->stream << progress;
stream->stream++;
}
unsigned int output, progress, read;
output = *stream->stream >> stream->bit;
memcpy(&read, stream->stream, 4);
output = read >> stream->bit;
output &= (1 << bits) - 1;
stream->stream += (stream->bit + bits) / 8;
stream->bit = (stream->bit + bits) & 7;
return output;
}
@ -57,6 +56,7 @@ unsigned int hxa_inflate_length_base[30] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15,
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};
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};
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};
typedef struct {
unsigned short table[16];
unsigned short translation[288];
@ -140,11 +140,11 @@ static void hxa_inflate_decode_tree(HxAInflateBitStream *stream, HXAInflateTree
hclen = hxa_inflate_read_bits(stream, 4) + 4;
for(i = 0; i < 19; i++)
lengths[i] = 0;
lengths[i] = 0;
/* read code lengths for code length alphabet */
for(i = 0; i < hclen; ++i)
lengths[hxa_inflate_code_length[i]] = hxa_inflate_read_bits(stream, 3);/* get 3 bits code length (0-7) */
lengths[hxa_inflate_code_length[i]] = hxa_inflate_read_bits(stream, 3);/* get 3 bits code length (0-7) */
/* build code length tree */
@ -158,17 +158,18 @@ static void hxa_inflate_decode_tree(HxAInflateBitStream *stream, HXAInflateTree
{
switch((symbol - 16) % 4)
{
case 16:
case 0:
previous = lengths[count - 1];
length = hxa_inflate_read_bits(stream, 2) + 3;
for(i = 0; i < length; i++)
lengths[count++] = previous;
break;
case 17:
case 1:
length = hxa_inflate_read_bits(stream, 3) + 3;
for(i = 0; i < length; i++)
lengths[count++] = 0;
case 18:
lengths[count++] = 0;
break;
case 2:
length = hxa_inflate_read_bits(stream, 7) + 11;
for(i = 0; i < length; i++)
lengths[count++] = 0;
@ -190,7 +191,7 @@ int hxa_inflate_decode(HxAInflateBitStream *stream, unsigned char *output, size_
for(value = hxa_tree_lookup(stream, lt); value != 256; value = hxa_tree_lookup(stream, lt))
{
if(value < 256)
output[*output_length++] = value;
output[(*output_length)++] = value;
else if(value > 288)
{
printf("HxA Error: Deflate error. Compressed block has length that is out of bounds.\n");
@ -201,11 +202,11 @@ int hxa_inflate_decode(HxAInflateBitStream *stream, unsigned char *output, size_
length = hxa_inflate_read_bits(stream, hxa_inflate_length_bits[value]) + hxa_inflate_length_base[value];
distance = hxa_tree_lookup(stream, dt);
offset = hxa_inflate_read_bits(stream, hxa_inflate_distance_bits[distance]) + hxa_inflate_distance_base[distance];
if(offset <= length)
memcpy(output[*output_length], output[*output_length - offset], length);
if(offset >= length)
memcpy(&output[*output_length], &output[*output_length - offset], length);
else
for(i = 0; i < length; ++i)
output[*output_length + i] = output[i - offset];
output[*output_length + i] = output[*output_length + i - offset];
*output_length += length;
}
}

View File

@ -84,7 +84,7 @@ unsigned int *hxa_neighbour_node(HXANode *node)
{
counter++;
clear++;
r = hxa_ref(i);
r = hxa_ref(ref, i);
cor = v[r];
if(cor == -1)
{
@ -96,7 +96,7 @@ unsigned int *hxa_neighbour_node(HXANode *node)
{
a = hxa_corner_get_previous(ref, i);
b = hxa_corner_get_next(ref, cor);
if(n[cor] == -1 && n[a] == -1 && hxa_ref(a) == hxa_ref(b))
if(n[cor] == -1 && n[a] == -1 && hxa_ref(ref, a) == hxa_ref(ref, b))
{
n[a] = cor;
n[cor] = a;
@ -111,7 +111,7 @@ unsigned int *hxa_neighbour_node(HXANode *node)
}
a = hxa_corner_get_next(ref, i);
b = hxa_corner_get_previous(ref, cor);
if(n[i] == -1 && n[b] == -1 && hxa_ref(a) == hxa_ref(b))
if(n[i] == -1 && n[b] == -1 && hxa_ref(ref, a) == hxa_ref(ref, b))
{
n[i] = b;
n[b] = i;

153
hxa_util_normals.c Normal file
View File

@ -0,0 +1,153 @@
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#pragma warning(disable:4703)
#pragma warning(disable:4996)
#pragma warning(disable:4664)
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
/* use include and defines to creat float and double versions of the normal functions. */
#define NORMAL_FACE
#define HXATYPE_DATA float_data
#define HXATYPE float
#define hxa_util_normal_face_macro hxa_util_normal_facef
#include "hxa_util_normals.h"
#define HXATYPE_DATA double_data
#define HXATYPE double
#define hxa_util_normal_face_macro hxa_util_normal_faced
#include "hxa_util_normals.h"
#undef NORMAL_FACE
#define NORMAL_CORNER
#define HXATYPE_DATA float_data
#define HXATYPE float
#define hxa_util_normal_corner_macro hxa_util_normal_cornerf
#include "hxa_util_normals.h"
#define HXATYPE_DATA double_data
#define HXATYPE double
#define hxa_util_normal_corner_macro hxa_util_normal_cornerd
#include "hxa_util_normals.h"
#define HXATYPE_DATA float_data
#define HXATYPE float
#define HXA_CREASE_TYPE unsigned char
#define hxa_util_normal_corner_macro hxa_util_normal_cornerf_u8
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE int
#define hxa_util_normal_corner_macro hxa_util_normal_cornerf_i32
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE float
#define hxa_util_normal_corner_macro hxa_util_normal_cornerf_f
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE double
#define hxa_util_normal_corner_macro hxa_util_normal_cornerf_d
#include "hxa_util_normals.h"
#define HXATYPE_DATA double_data
#define HXATYPE double
#define HXA_CREASE_TYPE unsigned char
#define hxa_util_normal_corner_macro hxa_util_normal_cornerd_u8
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE int
#define hxa_util_normal_corner_macro hxa_util_normal_cornerd_i32
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE float
#define hxa_util_normal_corner_macro hxa_util_normal_cornerd_f
#include "hxa_util_normals.h"
#define HXA_CREASE_TYPE double
#define hxa_util_normal_corner_macro hxa_util_normal_cornerd_d
#include "hxa_util_normals.h"
void hxa_util_normal_face(HXANode *node)
{
HXALayer *layer;
node->content.geometry.face_stack.layer_count++;
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);
layer = &node->content.geometry.face_stack.layers[node->content.geometry.face_stack.layer_count - 1];
layer->type = node->content.geometry.vertex_stack.layers[0].type;
layer->components = 3;
sprintf(layer->name, HXA_CONVENTION_SOFT_LAYER_NORMALS);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
layer->data.float_data = hxa_util_normal_facef(node);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
layer->data.double_data = hxa_util_normal_facef(node);
}
void hxa_util_normal_corner(HXANode *node)
{
char *crease_name = HXA_CONVENTION_SOFT_LAYER_CREASES;
HXALayer *layer;
unsigned int i, j, *neighbour, *face_ref;
int *ref;
void *face_data;
node->content.geometry.corner_stack.layer_count++;
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);
layer = &node->content.geometry.corner_stack.layers[node->content.geometry.corner_stack.layer_count - 1];
layer->type = node->content.geometry.vertex_stack.layers[0].type;
layer->components = 3;
sprintf(layer->name, HXA_CONVENTION_SOFT_LAYER_NORMALS);
face_ref = malloc((sizeof *face_ref) * node->content.geometry.edge_corner_count);
ref = node->content.geometry.corner_stack.layers[0].data.int32_data;
for(i = j = 0; i < node->content.geometry.edge_corner_count; i++)
{
face_ref[i] = j;
if(ref[i] < 0)
j++;
}
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
face_data = hxa_util_normal_facef(node);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
face_data = hxa_util_normal_faced(node);
neighbour = hxa_neighbour_node(node);
for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++)
{
for(j = 0; node->content.geometry.edge_stack.layers[i].name[j] == crease_name[j] && crease_name[j] != 0; j++);
if(node->content.geometry.edge_stack.layers[i].name[j] == crease_name[j])
{
switch(node->content.geometry.edge_stack.layers[i].type)
{
case HXA_LDT_UINT8 :
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
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);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
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);
break;
case HXA_LDT_INT32 :
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
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);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
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);
break;
case HXA_LDT_FLOAT :
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
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);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
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);
break;
case HXA_LDT_DOUBLE :
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
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);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
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);
break;
}
free(face_ref);
free(face_data);
return;
}
}
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
layer->data.float_data = hxa_util_normal_cornerf(node, neighbour, (float *)face_data, face_ref);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
layer->data.double_data = hxa_util_normal_cornerd(node, neighbour, (double *)face_data, face_ref);
free(face_ref);
free(face_data);
}

170
hxa_util_normals.h Normal file
View File

@ -0,0 +1,170 @@
/* Do not include or call anything defined in this .h file. It is exclusivly for the use of hxa_util_normals.c */
#ifdef NORMAL_FACE
HXATYPE *hxa_util_normal_face_macro(HXANode *node)
{
HXATYPE v1[3], v2[3], f, *normals, *n, *vertex, *a, *b, *c;
unsigned int i, j, count;
int *ref;
ref = node->content.geometry.corner_stack.layers[HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID].data.int32_data;
vertex = node->content.geometry.vertex_stack.layers[HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_ID].data.HXATYPE_DATA;
n = normals = malloc((sizeof *normals) * node->content.geometry.face_count * 3);
for(i = 0; i < node->content.geometry.edge_corner_count;)
{
if(ref[i + 2] < 0) /* Triangle */
{
a = &vertex[hxa_ref(ref, i) * 3];
b = &vertex[hxa_ref(ref, i) * 3 + 1];
c = &vertex[hxa_ref(ref, i) * 3 + 2];
v1[0] = a[0] - c[0];
v1[1] = a[1] - c[1];
v1[2] = a[2] - c[2];
v2[0] = b[0] - c[0];
v2[1] = b[1] - c[1];
v2[2] = b[2] - c[2];
n[0] = v1[1] * v2[2] - v1[2] * v2[1];
n[1] = v1[2] * v2[0] - v1[0] * v2[2];
n[2] = v1[0] * v2[1] - v1[1] * v2[0];
i += 3;
}else
{
count = node->content.geometry.edge_corner_count;
n[0] = n[1] = n[2] = 0;
for(j = 0; j < count; j++)
{
if(ref[i + j + 2] < 0)
count = j + 2 + 1;
a = &vertex[hxa_ref(ref, (i + j)) * 3];
b = &vertex[hxa_ref(ref, (i + (j + 1) % count)) * 3 + 1];
c = &vertex[hxa_ref(ref, (i + (j + 2) % count)) * 3 + 2];
v1[0] = a[0] - c[0];
v1[1] = a[1] - c[1];
v1[2] = a[2] - c[2];
v2[0] = b[0] - c[0];
v2[1] = b[1] - c[1];
v2[2] = b[2] - c[2];
n[0] += v1[1] * v2[2] - v1[2] * v2[1];
n[1] += v1[2] * v2[0] - v1[0] * v2[2];
n[2] += v1[0] * v2[1] - v1[1] * v2[0];
}
i + count;
}
f = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
n[0] /= f;
n[1] /= f;
n[2] /= f;
n += 3;
}
return normals;
}
#endif
#ifdef NORMAL_CORNER
HXATYPE *hxa_util_normal_corner_macro(HXANode *node,
unsigned int *neighburs,
#ifdef HXA_CREASE_TYPE
HXA_CREASE_TYPE *creases,
#endif
HXATYPE *face_normals,
unsigned int *faces)
{
HXATYPE *corner_normals, *n, tmp[3], f;
unsigned int i, r;
int * ref;
ref = node->content.geometry.corner_stack.layers[HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID].data.int32_data;
corner_normals = malloc((sizeof *corner_normals) * node->content.geometry.edge_corner_count * 3);
for(i = 0; i < node->content.geometry.edge_corner_count * 3; i++)
corner_normals[i] = 0;
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
{
if(corner_normals[i * 3] == 0 && corner_normals[i * 3 + 1] == 0 && corner_normals[i * 3 + 2] == 0)
{
r = i;
tmp[0] = tmp[1] = tmp[2] = 0;
while(TRUE)
{
n = &face_normals[faces[r]];
tmp[0] += n[0];
tmp[1] += n[1];
tmp[2] += n[2];
if(neighburs[r] == -1
#ifdef HXA_CREASE_TYPE
|| creases[r]
#endif
)
{
r = i;
while(r = neighburs[hxa_corner_get_next(ref, r)] != -1
#ifdef HXA_CREASE_TYPE
&& !creases[r]
#endif
)
{
n = &face_normals[faces[r]];
tmp[0] += n[0];
tmp[1] += n[1];
tmp[2] += n[2];
}
f = sqrt(tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2]);
tmp[0] /= f;
tmp[1] /= f;
tmp[2] /= f;
r = i;
while(TRUE)
{
corner_normals[r * 3] = tmp[0];
corner_normals[r * 3 + 1] = tmp[1];
corner_normals[r * 3 + 2] = tmp[2];
if(neighburs[r] == -1
#ifdef HXA_CREASE_TYPE
|| creases[r]
#endif
)
{
r = i;
while(r = neighburs[hxa_corner_get_next(ref, r)] != -1
#ifdef HXA_CREASE_TYPE
&& !creases[r]
#endif
)
{
corner_normals[r * 3] = tmp[0];
corner_normals[r * 3 + 1] = tmp[1];
corner_normals[r * 3 + 2] = tmp[2];
}
break;
}
r = hxa_corner_get_next(ref, neighburs[r]);
}
break;
}
r = hxa_corner_get_next(ref, neighburs[r]);
if(r == i)
{
f = sqrt(tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2]);
tmp[0] /= f;
tmp[1] /= f;
tmp[2] /= f;
while(TRUE)
{
corner_normals[r * 3] = tmp[0];
corner_normals[r * 3 + 1] = tmp[1];
corner_normals[r * 3 + 2] = tmp[2];
r = hxa_corner_get_next(ref, neighburs[r]);
if(r == i)
break;
}
break;
}
}
}
}
return corner_normals;
}
#endif

View File

@ -1,38 +1,59 @@
#include "hxa.h"
extern HXAFile *hxa_load(char *file_name, int silent);
extern int hxa_save(char *file_name, HXAFile *data);
extern void hxa_util_free_node_content(HXANode *node);
extern void hxa_util_free_file(HXAFile *file);
/* ------- disk stoarge ------------
Functions for saving and loading HxA files to and from disk. */
extern HXAFile *hxa_load(char *file_name, int silent); /* Load a Hxa file in to memory.*/
extern int hxa_save(char *file_name, HXAFile *data); /* Save a HxA structure to disk. */
extern void hxa_util_free_node_content(HXANode *node); /* frees the content of a node but does not free the node pointer itself */
extern void hxa_util_free_file(HXAFile *file); /* Frees an entire HxA structure. */
/* ------- validation ------------
Validates that the content of HxA structure. */
extern int hxa_util_validate(HXAFile *file, int silent); /* Validates the HxA file to contain valid data. */
extern int hxa_util_validate_pow(HXAFile *file, int silent); /* Validate that all images are of Power of two resolution. */
extern void hxa_print(HXAFile *file, int data);
extern void hxa_print_meta_find(HXAFile *file, char *key);
#define hxa_ref(a) (ref[a] >= 0 ? ref[a] : (-ref[a] - 1))
extern int hxa_corner_get_next(int *ref, unsigned int corner);
extern int hxa_corner_get_previous(int *ref, unsigned int corner);
/* ------- validation ------------
Validates that the content of HxA structure. */
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.*/
extern void hxa_print_meta_find(HXAFile *file, char *key);
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.*/
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*/
extern unsigned int hxa_util_meta_get_next(HXAMeta *meta_data, hxa_uint32 start, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type);
#define hxa_ref(ref, a) (ref[a] >= 0 ? ref[a] : (-ref[a] - 1)) /* A macro that converts all ref values to positive references. */
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. */
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. */
extern int hxa_edge_get_next(int *ref, unsigned int *neighbour, unsigned int edge);
extern int hxa_edge_get_previous(int *ref, unsigned int *neighbour, unsigned int edge);
extern unsigned int *hxa_neighbour_node(HXANode *node); /* Generates edge adjacensy information for a geometry mesh. */
extern void hxa_neighbour_file(HXAFile *file); /* Generates neighbour data for all geometry nodes in a HxA structure. */
extern HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b);
extern HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b); /* Merges two HxA structures in to one. */
extern unsigned int *hxa_neighbour_node(HXANode *node);
extern void hxa_neighbour_file(HXAFile *file);
extern void hxa_util_convert_layer_float_to_double(HXALayer *layer, unsigned int count);
extern void hxa_util_convert_layer_double_to_float(HXALayer *layer, unsigned int count);
extern void hxa_util_convert_stack_float_to_double(HXALayerStack *stack, unsigned int count);
extern void hxa_util_convert_stack_double_to_float(HXALayerStack *stack, unsigned int count);
extern void hxa_util_convert_node_float_to_double(HXANode *node);
extern void hxa_util_convert_node_double_to_float(HXANode *node);
extern void hxa_util_node_vertex_purge(HXANode *node);
extern void hxa_util_vertex_purge(HXAFile *file);
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. */
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. */
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. */
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. */
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. */
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. */
extern void hxa_util_triangulate_node(HXANode *node, unsigned int max_sides);
extern void hxa_util_node_vertex_purge(HXANode *node); /* removes any unused vertices from a node */
extern void hxa_util_vertex_purge(HXAFile *file); /* removes any unused vertices from a structure */
extern void hxa_close_node(HXANode *node);
extern void hxa_close_file(HXAFile *file);
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. */
extern void hxa_corner_to_vertex(HXANode *node); /**/
extern void hxa_close_node(HXANode *node); /* Closes all holes in a polygon mesh */
extern void hxa_close_file(HXAFile *file); /* Closes all holes in all polygon meshes */
extern HXAFile *hxa_fbx_load(char *file_name, HXAFile *hxa_file);