1
0
mirror of https://github.com/quelsolaar/HxA synced 2025-03-10 16:41:11 -04:00

new version that separates edge and corner stacks

This commit is contained in:
quelsolaar 2019-11-26 14:04:56 +01:00 committed by GitHub
parent e575c6c91a
commit 0a8b83a53e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1528 additions and 28 deletions

29
hxa.h
View File

@ -1,5 +1,4 @@
/* ------------- HxA 3D asset format ---------------*/
/*
/* ------------- HxA 3D asset format ---------------
HxA is a interchangeable graphics asset format. Written by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
Rational:
@ -30,9 +29,9 @@ The data is story in a number of nodes that are stored in an array. Each node st
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.
HaX stores 3 kinds of nodes
 -Pixel data.
 -Polygon geometry data.
 -Meta data only.
-Pixel data.
-Polygon geometry data.
-Meta data only.
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
@ -58,7 +57,7 @@ Text strings stored in meta data are stored the same way as names, but instead o
#define HAX_INCLUDE
#define HXA_VERSION_API "0.3"
#define HXA_VERSION_FORMAT 2
#define HXA_VERSION_FORMAT 3
typedef unsigned char hxa_uint8;
typedef signed int hxa_int32;
@ -141,8 +140,8 @@ typedef struct{
/* Layers stacks are arrays of layers where all the layers have the same number of entries (polygons, edges, vertices or pixels) */
typedef struct{
hxa_uint32 layer_count;
HXALayer *layers;
hxa_uint32 layer_count; /* the number of loayers in a stack. */
HXALayer *layers; /* An array of layers. */
}HXALayerStack;
/* A file consists of an array of nodes, All noides have meta data. Geometry nodes have geometry, image nodes have pixels*/
@ -156,7 +155,8 @@ typedef struct{
hxa_uint32 vertex_count; // number of vertices
HXALayerStack vertex_stack; // stack of vertex arrays. the first layer is always the vertex positions
hxa_uint32 edge_corner_count; // number of corners
HXALayerStack edge_corner_stack; // stack of corner arrays, the first layer is allways a reference array (see below)
HXALayerStack corner_stack; // stack of corner arrays, the first layer is allways a reference array (see below)
HXALayerStack edge_stack; // stack of edge arrays
hxa_uint32 face_count; // number of polygons
HXALayerStack face_stack; // stack of per polygon data.
}geometry;
@ -192,11 +192,12 @@ If you use HxA for something not coverd by the conventiosns but need a conventio
#define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME "vertex"
#define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_ID 0
#define HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS 3
#define HXA_CONVENTION_HARD_BASE_EDGE_CORNER_LAYER_NAME "reference"
#define HXA_CONVENTION_HARD_BASE_EDGE_CORNER_LAYER_ID 0
#define HXA_CONVENTION_HARD_BASE_EDGE_CORNER_LAYER_COMPONENTS 3
#define HXA_CONVENTION_HARD_BASE_EDGE_CORNER_LAYER_TYPE HXA_LDT_INT32
#define HXA_CONVENTION_HARD_EDGE_CORNER_NEIGHBOUR "neighbour"
#define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME "reference"
#define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID 0
#define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS 1
#define HXA_CONVENTION_HARD_BASE_CORNER_LAYER_TYPE HXA_LDT_INT32
#define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME "neighbour"
#define HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_TYPE HXA_LDT_INT32
/* Soft Conventions */
/* ---------------- */

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"
@ -52,12 +57,13 @@ void hxa_util_free_node_content(HXANode *node)
switch(node->type)
{
case HXA_NT_GEOMETRY :
hxa_util_free_stack(&node->content.geometry.edge_corner_stack);
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.geometry.edge_corner_stack);
hxa_util_free_stack(&node->content.image.image_stack);
break;
}
}
@ -157,7 +163,8 @@ int hxa_load_meta(FILE *f, char *file_name, HXAMeta **meta, hxa_uint32 *count, i
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[m->array_length] = 0;
if(!hxa_load_data(f, m->value.node_value, sizeof(char) * m->array_length, file_name, silent))
return FALSE;
break;
case HXA_MDT_BINARY :
@ -205,9 +212,9 @@ int hxa_load_layer_stack(FILE *f, char *file_name, HXALayerStack *stack, unsigne
}
stack->layers[i].type = (unsigned int)type;
size = type_sizes[stack->layers[i].type] * stack->layers[i].components * length;
stack->layers->data.double_data = malloc(size);
stack->layers[i].data.double_data = malloc(size);
stack->layer_count++;
if(!hxa_load_data(f, stack->layers->data.double_data, sizeof(hxa_uint8) * size, file_name, silent))
if(!hxa_load_data(f, stack->layers[i].data.double_data, sizeof(hxa_uint8) * size, file_name, silent))
return FALSE;
}
return TRUE;
@ -273,7 +280,8 @@ HXAFile *hxa_load(char *file_name, int silent)
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.edge_corner_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 :
@ -314,11 +322,19 @@ HXAFile *hxa_load(char *file_name, int silent)
hxa_util_free_file(file);
return NULL;
}
if(!hxa_load_layer_stack(f, file_name, &node[i].content.geometry.edge_corner_stack, node[i].content.geometry.edge_corner_count, silent))
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);
@ -452,7 +468,8 @@ int hxa_save(char *file_name, HXAFile *data)
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.edge_corner_stack, node->content.geometry.edge_corner_count);
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;

View File

@ -172,7 +172,8 @@ void hxa_print(HXAFile *file, int data)
printf("\t-Geometry vertex count: %u\n", file->node_array[i].content.geometry.vertex_count);
hxa_print_layer_stack(&file->node_array[i].content.geometry.vertex_stack, "Vertex", data, file->node_array[i].content.geometry.vertex_count);
printf("\t-Geometry edge count: %u\n", file->node_array[i].content.geometry.edge_corner_count);
hxa_print_layer_stack(&file->node_array[i].content.geometry.edge_corner_stack, "Edge", data, file->node_array[i].content.geometry.edge_corner_count);
hxa_print_layer_stack(&file->node_array[i].content.geometry.corner_stack, "Corner", data, file->node_array[i].content.geometry.edge_corner_count);
hxa_print_layer_stack(&file->node_array[i].content.geometry.edge_stack, "Edge", data, file->node_array[i].content.geometry.edge_corner_count);
printf("\t-Geometry face count: %u\n", file->node_array[i].content.geometry.face_count);
hxa_print_layer_stack(&file->node_array[i].content.geometry.face_stack, "Face", data, file->node_array[i].content.geometry.face_count);
break;

305
hxa_util_close.c Normal file
View File

@ -0,0 +1,305 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "hxa.h"
#include "hxa_utils.h"
typedef struct{
unsigned int edge;
unsigned int original;
float value;
void *next;
void *previous;
}HxAHoleEdge;
float un_hole_vector_normalized3f(float *vec, float *start, float *end)
{
float f;
vec[0] = end[0] - start[0];
vec[1] = end[1] - start[1];
vec[2] = end[2] - start[2];
f = sqrtf(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
vec[0] /= f;
vec[1] /= f;
vec[2] /= f;
return f;
}
void un_hole_normal3f(float *output, float *a, float *b, float *c)
{
float a2[3], b2[3], f;
a2[0] = a[0] - c[0];
a2[1] = a[1] - c[1];
a2[2] = a[2] - c[2];
b2[0] = b[0] - c[0];
b2[1] = b[1] - c[1];
b2[2] = b[2] - c[2];
f = sqrtf(a2[0] * a2[0] + a2[1] * a2[1] + a2[2] * a2[2]);
a2[0] /= f;
a2[1] /= f;
a2[2] /= f;
f = sqrtf(b2[0] * b2[0] + b2[1] * b2[1] + b2[2] * b2[2]);
b2[0] /= f;
b2[1] /= f;
b2[2] /= f;
output[0] = a2[1] * b2[2] - a2[2] * b2[1];
output[1] = a2[2] * b2[0] - a2[0] * b2[2];
output[2] = a2[0] * b2[1] - a2[1] * b2[0];
f = sqrtf(output[0] * output[0] + output[1] * output[1] + output[2] * output[2]);
output[0] /= f;
output[1] /= f;
output[2] /= f;
}
float un_hole_edge_length(int *ref, float *vertex, unsigned int edge)
{
float vec[3];
int v1, v2;
v1 = ref[edge];
if(v1 < 0)
v1 = -1 - v1;
edge = hxa_corner_get_next(ref, edge);
v2 = ref[edge];
if(v2 < 0)
v2 = -1 - v2;
v1 *= 3;
v2 *= 3;
vec[0] = vertex[v1 + 0] - vertex[v2 + 0];
vec[1] = vertex[v1 + 1] - vertex[v2 + 1];
vec[2] = vertex[v1 + 2] - vertex[v2 + 2];
return vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2];
}
float un_hole_edge_rate(int *ref, float *vertex, unsigned int *neighbour, unsigned int edge_a, unsigned int edge_b, unsigned int edge_c)
{
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;
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;
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;
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)
f = 0.1;
un_hole_vector_normalized3f(v0, &vertex[vr[1]], &vertex[vr[0]]);
un_hole_vector_normalized3f(v1, &vertex[vr[1]], &vertex[vr[2]]);
f *= 1.0 + v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
if(f != f)
f = 0.0;
return f;
}
unsigned int hxa_hole_close_one(int *ref, unsigned int ref_length, float *vertex_array, unsigned int *neighbour, unsigned int edge, HxAHoleEdge *buffer)
{
HxAHoleEdge *start, *next, *found;
unsigned int i, count = 0;
i = edge;
while(1)
{
buffer[count].edge = i;
buffer[count].original = i;
buffer[count].next = &buffer[count + 1];
buffer[count].previous = &buffer[count - 1];
i = hxa_edge_get_next(ref, neighbour, i);
count++;
if(i == edge)
break;
}
buffer[count - 1].next = &buffer[0];
buffer[0].previous = &buffer[count - 1];
for(i = 0; i < count; i++)
{
buffer[i].value = un_hole_edge_rate(ref, vertex_array, neighbour, buffer[i].edge, buffer[(i + 1) % count].edge, buffer[(i + 2) % count].edge);
}
start = buffer;
while(count != 0)
{
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;
neighbour[ref_length + 1] = next->edge;
neighbour[ref_length + 2] = found->edge;
neighbour[next->edge] = ref_length + 1;
neighbour[found->edge] = ref_length + 2;
if(count == 3)
{
neighbour[ref_length] = ((HxAHoleEdge *)next->next)->edge;
neighbour[((HxAHoleEdge *)next->next)->edge] = ref_length;
return ref_length + 3;
}else
neighbour[ref_length] = -1;
if(count == 3)
break;
found->next = ((HxAHoleEdge *)found->next)->next;
((HxAHoleEdge *)found->next)->previous = found;
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 + 2))
found->value *= 0.95;
else
((HxAHoleEdge *)found->previous)->value *= 0.95;
ref_length += 3;
start = found;
count--;
}
return ref_length;
}
void hxa_close_node_extend_layer(HXALayer *layer, unsigned int last_length, unsigned int new_length)
{
HXALayer l;
unsigned int i, length;
switch(layer->type)
{
case HXA_LDT_UINT8 :
length = (sizeof *l.data.uint8_data) * last_length * layer->components;
l.data.uint8_data = malloc(length);
memcpy(l.data.uint8_data, layer->data.uint8_data, length);
length = new_length * layer->components;
for(i = new_length * layer->components; i < length; i++)
l.data.uint8_data[i] = 0;
free(layer->data.uint8_data);
layer->data.uint8_data = l.data.uint8_data;
break;
case HXA_LDT_INT32 :
length = (sizeof *l.data.int32_data) * last_length * layer->components;
l.data.int32_data = malloc(length);
memcpy(l.data.int32_data, layer->data.int32_data, length);
length = new_length * layer->components;
for(i = new_length * layer->components; i < length; i++)
l.data.int32_data[i] = 0;
free(layer->data.int32_data);
layer->data.int32_data = l.data.int32_data;
break;
case HXA_LDT_FLOAT :
length = (sizeof *l.data.float_data) * last_length * layer->components;
l.data.float_data = malloc(length);
memcpy(l.data.float_data, layer->data.float_data, length);
length = new_length * layer->components;
for(i = new_length * layer->components; i < length; i++)
l.data.float_data[i] = 0;
free(layer->data.float_data);
layer->data.float_data = l.data.float_data;
break;
case HXA_LDT_DOUBLE :
length = (sizeof *l.data.double_data) * last_length * layer->components;
l.data.double_data = malloc(length);
memcpy(l.data.double_data, layer->data.double_data, length);
length = new_length * layer->components;
for(i = new_length * layer->components; i < length; i++)
l.data.double_data[i] = 0;
free(layer->data.double_data);
layer->data.double_data = l.data.double_data;
break;
}
}
void hxa_close_node(HXANode *node)
{
char *name = HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME;
HxAHoleEdge *edge_buffer;
float *vertex_array;
unsigned int i, j, count, *n, *n2;
signed int *ref;
if(node->type != HXA_NT_GEOMETRY || node->content.geometry.vertex_count == 0 || node->content.geometry.edge_corner_count == 0)
return;
n = hxa_neighbour_node(node);
for(count = i = 0; i < node->content.geometry.edge_corner_count; i++)
if(n[i] == -1)
count++;
if(count == 0)
{
free(n);
return;
}
ref = malloc((sizeof *ref) * (node->content.geometry.edge_corner_count + count * 3));
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
{
ref[i] = node->content.geometry.corner_stack.layers[0].data.int32_data[i];
}
n2 = malloc((sizeof *ref) * (node->content.geometry.edge_corner_count + count * 3));
memcpy(n2, n, (sizeof *n2) * node->content.geometry.edge_corner_count);
free(n);
edge_buffer = malloc((sizeof *edge_buffer) * count);
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
{
count = node->content.geometry.vertex_count * 3;
vertex_array = malloc((sizeof *vertex_array) * count);
for(i = 0; i < count; i++)
vertex_array[i] = (float)node->content.geometry.vertex_stack.layers[0].data.double_data[i];
}else
vertex_array = node->content.geometry.vertex_stack.layers[0].data.float_data;
count = node->content.geometry.edge_corner_count;
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
if(n2[i] == -1)
count = hxa_hole_close_one(ref, count, vertex_array, n2, i, edge_buffer);
free(node->content.geometry.corner_stack.layers->data.int32_data);
node->content.geometry.corner_stack.layers->data.int32_data = ref;
for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++)
hxa_close_node_extend_layer(&node->content.geometry.corner_stack.layers[i], node->content.geometry.edge_corner_count, count);
for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++)
{
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++);
if(name[j] == node->content.geometry.corner_stack.layers[i].name[j])
{
memcpy(node->content.geometry.corner_stack.layers[i].data.int32_data, n2, sizeof(hxa_int32) * count);
}else
hxa_close_node_extend_layer(&node->content.geometry.edge_stack.layers[i], node->content.geometry.edge_corner_count, count);
}
for(i = 0; i < node->content.geometry.face_stack.layer_count; i++)
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);
node->content.geometry.face_count += (count - node->content.geometry.edge_corner_count) / 3;
node->content.geometry.edge_corner_count = count;
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_DOUBLE)
free(vertex_array);
free(n2);
free(edge_buffer);
}
void hxa_close_file(HXAFile *file)
{
unsigned int i;
hxa_print(file, 0);
for(i = 0; i < file->node_count; i++)
hxa_close_node(&file->node_array[i]);
hxa_print(file, 0);
i = 0;
}

View File

@ -7,17 +7,38 @@
#define FALSE 0
#define TRUE !FALSE
int hxa_convert_param_to_int(char *string, unsigned int *output)
{
*output = 0;
if(string[0] < '0' && string[0] > '9')
return FALSE;
while(string[0] < '0' && string[0] > '9')
{
*output *= 10;
*output += (unsigned int)string[0] - (unsigned int)'0';
}
return TRUE;
}
int main(int argc, char **argv)
{
HXAFile *file;
unsigned int i, silent, save;
HXAFile *file, *file2;
unsigned int i, j, silent, save, int_param;
if(argc < 2)
{
printf("HxA utility. Written by Eskil Steenberg www.quelsolaar.com. MIT License\n");
printf("Usage: %s <file in> <optional file out> <arguments>\n", argv[0]);
printf("argument operations are executed in order.\n");
printf("Argument list:\n");
printf(" - \"validate\" validates the file to make sure it is correct. Non valid files may cause the tools to fail.\n");
printf(" - \"powvalid\" validates that all images in a file have power of two resolution.\n");
printf(" - \"neighbour\" compute a neighbour layer storing adjacency.\n");
printf(" - \"save\" <filename> write out the file.\n");
printf(" - \"d2f\" converts all double precission layers to float layers.\n");
printf(" - \"f2d\" converts all float layers to double precission layers.\n");
printf(" - \"triangulate\" <max sides> Converts all polygons with more sides then <max sides> in to triangles.\n");
printf(" - \"vertexpurge\" Removes any unreferenced vertex from the file.\n");
printf(" - \"close\" Closes any holes in meshes.\n");
printf(" - \"print\" prints the structure of the file.\n");
printf(" - \"printall\" prints the structure and data the file.\n");
printf(" - \"printmeta\" <key> prints the value of meta entries of a specific name.\n");
@ -43,7 +64,7 @@ int main(int argc, char **argv)
{
if(!silent)
printf("Saving HxA file: %s\n", argv[i]);
if(!hxa_save(argv[2], file) && !silent)
if(!hxa_save(argv[i], file) && !silent)
{
printf("Saving file failed. Exiting...\n");
return FALSE;
@ -53,6 +74,42 @@ int main(int argc, char **argv)
printf("HxA Error: \"save\" is missing a filename parameter. Exiting...\n");
return FALSE;
}
}else if(strcmp(argv[i], "validate") == 0)
{
if(!hxa_util_validate(file, silent))
return FALSE;
}else if(strcmp(argv[i], "powvalid") == 0)
{
if(!hxa_util_validate_pow(file, silent))
return FALSE;
}else if(strcmp(argv[i], "neighbour") == 0)
{
hxa_neighbour_file(file);
}else if(strcmp(argv[i], "f2d") == 0)
{
for(j = 0; j < file->node_count; j++)
hxa_util_convert_node_float_to_double(&file->node_array[j]);
}else if(strcmp(argv[i], "d2f") == 0)
{
for(j = 0; j < file->node_count; j++)
hxa_util_convert_node_double_to_float(&file->node_array[j]);
}else if(strcmp(argv[i], "triangulate") == 0)
{
if(hxa_convert_param_to_int(argv[++i], &int_param) && int_param > 2)
{
for(j = 0; j < file->node_count; j++)
hxa_util_triangulate_node(&file->node_array[j], int_param);
}else
{
printf("HxA Error: the command param \"triangulate\" must be a folowed by a integer param set to 3 or larger");
return FALSE;
}
}else if(strcmp(argv[i], "vertexpurge") == 0)
{
hxa_util_vertex_purge(file);
}else if(strcmp(argv[i], "close") == 0)
{
hxa_close_file(file);
}else if(strcmp(argv[i], "print") == 0)
{
hxa_print(file, FALSE);
@ -67,7 +124,14 @@ int main(int argc, char **argv)
{
printf("HxA Error: \"printmeta\" is missing a key parameter. Exiting...\n");
return FALSE;
}
}
}else if(strcmp(argv[i], "merge") == 0)
{
file2 = hxa_load(argv[++i], silent);
if(file2 != NULL)
hxa_util_merge(file, file2);
else
return FALSE;
}else
{
if(i == 2)

113
hxa_util_convert.c Normal file
View File

@ -0,0 +1,113 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
void hxa_util_convert_layer_float_to_double(HXALayer *layer, unsigned int count)
{
unsigned int j, length;
double *d;
float *f;
if(layer->type == HXA_LDT_FLOAT)
{
length = layer->components * count;
f = layer->data.float_data;
layer->data.double_data = d = malloc((sizeof *d) * length);
for(j = 0; j < length; j++)
d[j] = (double)f[j];
free(f);
layer->type = HXA_LDT_DOUBLE;
}
}
void hxa_util_convert_layer_double_to_float(HXALayer *layer, unsigned int count)
{
unsigned int j, length;
double *d;
float *f;
if(layer->type == HXA_LDT_DOUBLE)
{
length = layer->components * count;
d = layer->data.double_data;
layer->data.float_data = f = malloc((sizeof *f) * length);
for(j = 0; j < length; j++)
f[j] = (double)d[j];
free(d);
layer->type = HXA_LDT_FLOAT;
}
}
void hxa_util_convert_stack_float_to_double(HXALayerStack *stack, unsigned int count)
{
unsigned int i;
for(i = 0; i < stack->layer_count; i++)
hxa_util_convert_layer_float_to_double(&stack->layers[i], count);
}
void hxa_util_convert_stack_double_to_float(HXALayerStack *stack, unsigned int count)
{
unsigned int i;
for(i = 0; i < stack->layer_count; i++)
hxa_util_convert_layer_double_to_float(&stack->layers[i], count);
}
void hxa_util_convert_node_float_to_double(HXANode *node)
{
if(node->type == HXA_NT_GEOMETRY)
{
hxa_util_convert_stack_float_to_double(&node->content.geometry.vertex_stack, node->content.geometry.vertex_count);
hxa_util_convert_stack_float_to_double(&node->content.geometry.corner_stack, node->content.geometry.edge_corner_count);
hxa_util_convert_stack_float_to_double(&node->content.geometry.edge_stack, node->content.geometry.edge_corner_count);
hxa_util_convert_stack_float_to_double(&node->content.geometry.face_stack, node->content.geometry.face_count);
}
if(node->type == HXA_NT_IMAGE)
{
switch(node->content.image.type)
{
case HXA_IT_CUBE_IMAGE :
hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * 6);
break;
case HXA_IT_1D_IMAGE :
hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0]);
break;
case HXA_IT_2D_IMAGE :
hxa_util_convert_stack_float_to_double(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1]);
break;
case HXA_IT_3D_IMAGE :
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]);
break;
}
}
}
void hxa_util_convert_node_double_to_float(HXANode *node)
{
if(node->type == HXA_NT_GEOMETRY)
{
hxa_util_convert_stack_double_to_float(&node->content.geometry.vertex_stack, node->content.geometry.vertex_count);
hxa_util_convert_stack_double_to_float(&node->content.geometry.corner_stack, node->content.geometry.edge_corner_count);
hxa_util_convert_stack_double_to_float(&node->content.geometry.edge_stack, node->content.geometry.edge_corner_count);
hxa_util_convert_stack_double_to_float(&node->content.geometry.face_stack, node->content.geometry.face_count);
}
if(node->type == HXA_NT_IMAGE)
{
switch(node->content.image.type)
{
case HXA_IT_CUBE_IMAGE :
hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1] * 6);
break;
case HXA_IT_1D_IMAGE :
hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0]);
break;
case HXA_IT_2D_IMAGE :
hxa_util_convert_stack_double_to_float(&node->content.image.image_stack, node->content.image.resolution[0] * node->content.image.resolution[1]);
break;
case HXA_IT_3D_IMAGE :
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]);
break;
}
}
}

51
hxa_util_merge_split.c Normal file
View File

@ -0,0 +1,51 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
void hxa_util_merge_meta(HXAMeta *meta, int add)
{
unsigned int i;
if(meta->type == HXA_MDT_NODE)
for(i = 0; meta->array_length; i++)
meta->value.node_value[i] += add;
if(meta->type == HXA_MDT_META)
for(i = 0; meta->array_length; i++)
hxa_util_merge_meta(&((HXAMeta *)meta->value.node_value)[i], add);
}
HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b)
{
unsigned int i, j;
for(i = 0; i < file_b->node_count; j++)
for(j = 0; j > file_b->node_array[i].meta_data_count; j++)
hxa_util_merge_meta(&file_b->node_array[i].meta_data[j], file_a->node_count);
file_b->node_array = realloc(file_b->node_array, (sizeof *file_b->node_array) * (file_a->node_count + file_b->node_count));
memcpy(&file_a->node_array[file_a->node_count], file_b->node_array, (sizeof *file_b->node_array) * file_b->node_count);
file_a->node_count += file_b->node_count;
free(file_b->node_array);
free(file_b);
return file_a;
}
void hxa_util_node_remove(HXAFile *file, hxa_uint32 remove_node)
{
HXANode *new_nodes;
unsigned int i, j;
for(i = remove_node; i < file->node_count; j++)
for(j = 0; j > file->node_array[i].meta_data_count; j++)
hxa_util_merge_meta(&file->node_array[i].meta_data[j], -1);
file->node_count--;
new_nodes = malloc((sizeof *file->node_array) * (file->node_count));
if(remove_node != 0)
memcpy(new_nodes, file->node_array, (sizeof *file->node_array) * remove_node);
if(remove_node != file->node_count)
memcpy(&new_nodes[remove_node], &file->node_array[remove_node + 1], (sizeof *file->node_array) * (file->node_count - remove_node));
free(file->node_array);
file->node_array = new_nodes;
}

114
hxa_util_meta.c Normal file
View File

@ -0,0 +1,114 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
void hxa_util_meta_add(HXAMeta **meta_data, hxa_uint32 *meta_data_count, char *name, HXAMetaDataType type, void *data, unsigned int length, int copy)
{
HXAMeta *m;
unsigned int i;
*meta_data = realloc(*meta_data, (sizeof **meta_data) * (*meta_data_count + 1));
m = &(*meta_data)[(*meta_data_count)++];
for(i = 0; i < HXA_NAME_MAX_LENGTH - 1 && name[i] != 0; i++)
m->name[i] = name[i];
m->name[i] = 0;
m->type = type;
switch(type)
{
case HXA_MDT_INT64 :
if(copy)
{
m->value.int64_value = malloc((sizeof *m->value.int64_value) * length);
memcpy(m->value.int64_value, data, (sizeof *m->value.int64_value) * length);
}else
m->value.int64_value = data;
break;
case HXA_MDT_DOUBLE :
if(copy)
{
m->value.double_value = malloc((sizeof *m->value.double_value) * length);
memcpy(m->value.double_value, data, (sizeof *m->value.double_value) * length);
}else
m->value.int64_value = data;
break;
case HXA_MDT_NODE :
if(copy)
{
m->value.node_value = malloc((sizeof *m->value.node_value) * length);
memcpy(m->value.node_value, data, (sizeof *m->value.node_value) * length);
}else
m->value.int64_value = data;
break;
case HXA_MDT_TEXT :
for(length = 0; ((char *)data)[length] != 0; length++);
length++;
if(copy)
{
m->value.text_value = malloc((sizeof *m->value.text_value) * length);
memcpy(m->value.text_value, data, (sizeof *m->value.text_value) * length);
}else
m->value.text_value = data;
break;
case HXA_MDT_BINARY :
if(copy)
{
m->value.bin_value = malloc((sizeof *m->value.bin_value) * length);
memcpy(m->value.bin_value, data, (sizeof *m->value.bin_value) * length);
}else
m->value.bin_value = data;
break;
case HXA_MDT_META :
if(copy)
{
exit(0); // FIX ME!
}else
m->value.array_of_meta = data;
break;
}
m->array_length = length;
}
void *hxa_util_meta_get(HXAMeta *meta_data, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type, unsigned int *length, int recursive)
{
void *output;
unsigned int i, j;
for(i = 0; i < meta_data_count; i++)
{
if(meta_data[i].type == type)
{
for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++);
if(meta_data[i].name[j] == name[j])
{
if(length != NULL)
*length = meta_data[i].array_length;
return meta_data[i].value.array_of_meta;
}
}
if(recursive && meta_data[i].type == HXA_MDT_META)
if((output = hxa_util_meta_get(meta_data[i].value.array_of_meta, meta_data[i].array_length, name, type, length, TRUE)) != NULL)
return output;
}
return NULL;
}
unsigned int hxa_util_meta_get_next(HXAMeta *meta_data, hxa_uint32 start, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type)
{
unsigned int i, j;
for(i = start; i < meta_data_count; i++)
{
if(meta_data[i].type == type)
{
for(j = 0; meta_data[i].name[j] == name[j] && name[j] != 0; j++);
if(meta_data[i].name[j] == name[j])
return i;
}
}
return -1;
}

159
hxa_util_neighbour.c Normal file
View File

@ -0,0 +1,159 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
int hxa_corner_get_next(int *ref, unsigned int corner)
{
unsigned int i;
if(ref[corner] >= 0)
{
return corner + 1;
}else
{
for(i = corner - 1; i != 0; i--)
if(ref[i] < 0)
return i + 1;
return 0;
}
}
int hxa_corner_get_previous(int *ref, unsigned int corner)
{
unsigned int i;
if(corner == 0 || ref[corner - 1] < 0)
{
for(i = corner + 1; ref[i] >= 0; i++);
return i;
}else
return corner - 1;
}
int hxa_edge_get_next(int *ref, unsigned int *neighbour, unsigned int edge)
{
if(neighbour[edge] != -1)
return edge;
edge = hxa_corner_get_next(ref, edge);
while(neighbour[edge] != -1)
{
edge = neighbour[edge];
edge = hxa_corner_get_next(ref, edge);
}
return edge;
}
int hxa_edge_get_previous(int *ref, unsigned int *neighbour, unsigned int edge)
{
if(neighbour[edge] != -1)
return edge;
edge = hxa_corner_get_previous(ref, edge);
while(neighbour[edge] != -1)
{
edge = neighbour[edge];
edge = hxa_corner_get_previous(ref, edge);
}
return edge;
}
unsigned int *hxa_neighbour_node(HXANode *node)
{
char *name = HXA_CONVENTION_HARD_EDGE_NEIGHBOUR_LAYER_NAME;
unsigned int j, cor, clear = 0, *n, *v, r, a, b, vertex_count, edge_length;
unsigned int counter = 0, laps = 0;
int i, *ref;
vertex_count = node->content.geometry.vertex_count;
edge_length = node->content.geometry.edge_corner_count;
ref = node->content.geometry.corner_stack.layers[0].data.int32_data;
n = malloc((sizeof *n) * edge_length);
for(i = 0; i < edge_length; i++)
n[i] = -1;
v = malloc((sizeof *v) * vertex_count);
for(i = 0; i < vertex_count; i++)
v[i] = -1;
while(clear < edge_length)
{
for(i = 0; i < edge_length && clear < edge_length; i++)
{
counter++;
clear++;
r = hxa_ref(i);
cor = v[r];
if(cor == -1)
{
if(n[i] == -1 || n[hxa_corner_get_previous(ref, i)] == -1)
v[r] = i;
}else if(cor == i)
v[r] = -1;
else
{
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))
{
n[a] = cor;
n[cor] = a;
clear = 0;
if(n[hxa_corner_get_previous(ref, cor)] != -1)
{
if(n[i] == -1)
v[r] = i;
else
v[r] = -1;
}
}
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))
{
n[i] = b;
n[b] = i;
clear = 0;
if(n[cor] != -1)
{
if(n[hxa_corner_get_previous(ref, i)] == -1)
v[r] = i;
else
v[r] = -1;
}
}
}
}
laps++;
}
free(v);
for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++)
{
for(j = 0; node->content.geometry.edge_stack.layers[i].name[j] == name[j] && name[j] != 0; j++);
if(node->content.geometry.edge_stack.layers[i].name[j] == name[j])
{
free(node->content.geometry.edge_stack.layers[i].data.int32_data);
node->content.geometry.edge_stack.layers[i].data.int32_data = n;
return n;
}
}
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));
node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].data.int32_data = n;
node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].components = 1;
node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].type = HXA_LDT_INT32;
for(i = 0; name[i] != 0; i++)
node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].name[i] = name[i];
node->content.geometry.edge_stack.layers[node->content.geometry.edge_stack.layer_count].name[i] = 0;
node->content.geometry.edge_stack.layer_count++;
return n;
}
void hxa_neighbour_file(HXAFile *file)
{
unsigned int i;
for(i = 0; i < file->node_count; i++)
if(file->node_array[i].type == HXA_NT_GEOMETRY)
hxa_neighbour_node(&file->node_array[i]);
}

416
hxa_util_triangulate.c Normal file
View File

@ -0,0 +1,416 @@
#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
typedef enum{
HXA_UTIL_TEC_VALID,
HXA_UTIL_TEC_CONCAVE,
HXA_UTIL_TEC_OVERLAPING
}HxATrinagulateEdgeCategory;
typedef struct{
int vertex;
unsigned int origin;
HxATrinagulateEdgeCategory category;
double weight;
unsigned int worst_vertex;
}HxATrinagulateEdge;
void hxa_util_triangulate_ngon_edge_evaluate(HxATrinagulateEdge *edges, unsigned int edge_count, unsigned int active, double *vertex)
{
double normal[3], v0[3], v1[3], v2[3], t0[3], t1[3], t2[3], *base0, *base1, *middle, *test, f;
unsigned int i, first = TRUE;
base0 = &vertex[edges[active].vertex * 3];
middle = &vertex[edges[(active + 1) % edge_count].vertex * 3];
base1 = &vertex[edges[(active + 2) % edge_count].vertex * 3];
t0[0] = base0[0] - base1[0];
t0[1] = base0[1] - base1[1];
t0[2] = base0[2] - base1[2];
t1[0] = middle[0] - base1[0];
t1[1] = middle[1] - base1[1];
t1[2] = middle[2] - base1[2];
normal[0] = t0[1] * t1[2] - t0[2] * t1[1];
normal[1] = t0[2] * t1[0] - t0[0] * t1[2];
normal[2] = t0[0] * t1[1] - t0[1] * t1[0];
f = sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
normal[0] /= f;
normal[1] /= f;
normal[2] /= f;
v0[0] = base1[0] - base0[0];
v0[1] = base1[1] - base0[1];
v0[2] = base1[2] - base0[2];
v1[0] = base0[0] - middle[0];
v1[1] = base0[1] - middle[1];
v1[2] = base0[2] - middle[2];
v2[0] = middle[0] - base1[0];
v2[1] = middle[1] - base1[1];
v2[2] = middle[2] - base1[2];
t0[0] = v0[1] * normal[2] - v0[2] * normal[1];
t0[1] = v0[2] * normal[0] - v0[0] * normal[2];
t0[2] = v0[0] * normal[1] - v0[1] * normal[0];
t1[0] = v1[1] * normal[2] - v1[2] * normal[1];
t1[1] = v1[2] * normal[0] - v1[0] * normal[2];
t1[2] = v1[0] * normal[1] - v1[1] * normal[0];
t2[0] = v2[1] * normal[2] - v2[2] * normal[1];
t2[1] = v2[2] * normal[0] - v2[0] * normal[2];
t2[2] = v2[0] * normal[1] - v2[1] * normal[0];
edges[active].category = HXA_UTIL_TEC_VALID;
edges[active].weight = -1.0;
edges[active].worst_vertex = -1;
for(i = 0; i < edge_count - 3; i++)
{
test = &vertex[edges[(active + i + 3) % edge_count].vertex * 3];
f = t0[0] * (test[0] - base0[0]) + t0[1] * (test[1] - base0[1]) + t0[2] * (test[2] - base0[2]);
if(f > 0.0)
{
if(t1[0] * (test[0] - base0[0]) + t1[1] * (test[1] - base0[1]) + t1[2] * (test[2] - base0[2]) > 0 &&
t2[0] * (test[0] - base1[0]) + t2[1] * (test[1] - base1[1]) + t2[2] * (test[2] - base1[2]) > 0)
{
f = normal[0] * (test[0] - base0[0]) + normal[1] * (test[1] - base0[1]) + normal[2] * (test[2] - base0[2]);
if(f < 0)
f = f * -0.1;
if(edges[active].category < HXA_UTIL_TEC_OVERLAPING || f > edges[active].weight)
{
edges[active].category = HXA_UTIL_TEC_OVERLAPING;
edges[active].weight = f;
edges[active].worst_vertex = edges[(i + 3) % edge_count].vertex;
}
}else if(edges[active].category < HXA_UTIL_TEC_CONCAVE || (f > edges[active].weight && edges[active].category != HXA_UTIL_TEC_OVERLAPING))
{
edges[active].category = HXA_UTIL_TEC_CONCAVE;
edges[active].weight = -f;
edges[active].worst_vertex = edges[(i + 3) % edge_count].vertex;
}
}
}
if(edges[active].category == HXA_UTIL_TEC_VALID)
{
f = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
v1[0] /= f;
v1[1] /= f;
v1[2] /= f;
f = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
v2[0] /= f;
v2[1] /= f;
v2[2] /= f;
edges[active].weight = 1 + v1[0] * -v2[0] + v1[1] * -v2[1] + v1[2] * -v2[2];
}
}
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)
{
HxATrinagulateEdge edge_buffers[1024], *e;
unsigned int i, found, output_count = 0, update;
if(count < 1024)
e = edge_buffers;
else
e = malloc((sizeof *e) * count);
for(i = 0; i < count - 1; i++)
{
e[i].vertex = ref_ngon[i];
e[i].origin = origin_start + i;
}
e[i].vertex = (unsigned int)(-ref_ngon[i] - 1);
e[i].origin = origin_start + i;
for(i = 0; i < count; i++)
hxa_util_triangulate_ngon_edge_evaluate(e, count, i, vertex);
while(TRUE)
{
found = 0;
for(i = 1; i < count; i++)
if(e[i].category < e[found].category || (e[i].category == e[found].category && e[i].weight > e[found].weight))
found = i;
ref_output[output_count] = e[found].vertex;
ref_output[output_count + 1] = e[(found + 1) % count].vertex;
ref_output[output_count + 2] = -e[(found + 2) % count].vertex - 1;
if(origin_output != NULL)
{
origin_output[output_count] = e[found].origin;
origin_output[output_count + 1] = e[(found + 1) % count].origin;
origin_output[output_count + 2] = e[(found + 2) % count].origin;
}
output_count += 3;
update = e[(found + 1) % count].vertex;
found = (found + 1) % count;
for(i = found + 1; i < count; i++)
e[i - 1] = e[i];
count--;
if(count == 3)
break;
hxa_util_triangulate_ngon_edge_evaluate(e, count, (found + count - 2) % count, vertex);
hxa_util_triangulate_ngon_edge_evaluate(e, count, (found + count - 1) % count, vertex);
for(i = 0; i < count; i++)
if(e[i].worst_vertex == update)
hxa_util_triangulate_ngon_edge_evaluate(e, count, i, vertex);
}
ref_output[output_count] = e[0].vertex;
ref_output[output_count + 1] = e[1].vertex;
ref_output[output_count + 2] = -e[2].vertex - 1;
if(origin_output != NULL)
{
origin_output[output_count] = e[0].origin;
origin_output[output_count + 1] = e[1].origin;
origin_output[output_count + 2] = e[2].origin;
}
output_count += 3;
if(e != edge_buffers)
free(e);
return output_count;
}
void hxa_util_triangulate_re_ref_layer(HXALayer *layers, unsigned int count, unsigned int *re_ref)
{
unsigned int i, j, components;
components = layers->components;
switch(layers->type)
{
case HXA_LDT_UINT8 :
{
unsigned char *read, *write;
read = layers->data.uint8_data;
write = malloc((sizeof *write) * components * count);
layers->data.uint8_data = write;
for(i = 0; i < count; i++)
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
free(read);
}
break;
case HXA_LDT_INT32 :
{
int *read, *write;
read = layers->data.int32_data;
write = malloc((sizeof *write) * components * count);
layers->data.int32_data = write;
for(i = 0; i < count; i++)
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
free(read);
}
break;
case HXA_LDT_FLOAT :
{
float *read, *write;
read = layers->data.float_data;
write = malloc((sizeof *write) * components * count);
layers->data.float_data = write;
for(i = 0; i < count; i++)
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
free(read);
}
break;
case HXA_LDT_DOUBLE :
{
double *read, *write;
read = layers->data.double_data;
write = malloc((sizeof *write) * components * count);
layers->data.double_data = write;
for(i = 0; i < count; i++)
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
free(read);
}
break;
}
}
extern int hxa_corner_get_next(int *ref, unsigned int corner);
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)
{
unsigned int i, j, components;
int new_next, old_next;
components = layers->components;
switch(layers->type)
{
case HXA_LDT_UINT8 :
{
unsigned char *read, *write;
read = layers->data.uint8_data;
write = malloc((sizeof *write) * components * count);
layers->data.uint8_data = write;
for(i = 0; i < count; i++)
{
old_next = old_ref[hxa_corner_get_next(old_ref, i)];
new_next = new_ref[hxa_corner_get_next(new_ref, i)];
if(old_next < 0)
old_next = -old_next - 1;
if(new_next < 0)
new_next = -new_next - 1;
if(old_next == new_next)
{
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
}else
for(j = 0; j < components; j++)
write[i * components + j] = 0;
}
free(read);
}
break;
case HXA_LDT_INT32 :
{
int *read, *write;
read = layers->data.int32_data;
write = malloc((sizeof *write) * components * count);
layers->data.int32_data = write;
for(i = 0; i < count; i++)
{
old_next = old_ref[hxa_corner_get_next(old_ref, i)];
new_next = new_ref[hxa_corner_get_next(new_ref, i)];
if(old_next < 0)
old_next = -old_next - 1;
if(new_next < 0)
new_next = -new_next - 1;
if(old_next == new_next)
{
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
}else
for(j = 0; j < components; j++)
write[i * components + j] = 0;
}
free(read);
}
break;
case HXA_LDT_FLOAT :
{
float *read, *write;
read = layers->data.float_data;
write = malloc((sizeof *write) * components * count);
layers->data.float_data = write;
for(i = 0; i < count; i++)
{
old_next = old_ref[hxa_corner_get_next(old_ref, i)];
new_next = new_ref[hxa_corner_get_next(new_ref, i)];
if(old_next < 0)
old_next = -old_next - 1;
if(new_next < 0)
new_next = -new_next - 1;
if(old_next == new_next)
{
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
}else
for(j = 0; j < components; j++)
write[i * components + j] = 0;
}
free(read);
}
break;
case HXA_LDT_DOUBLE :
{
double *read, *write;
read = layers->data.double_data;
write = malloc((sizeof *write) * components * count);
layers->data.double_data = write;
for(i = 0; i < count; i++)
{
old_next = old_ref[hxa_corner_get_next(old_ref, i)];
new_next = new_ref[hxa_corner_get_next(new_ref, i)];
if(old_next < 0)
old_next = -old_next - 1;
if(new_next < 0)
new_next = -new_next - 1;
if(old_next == new_next)
{
for(j = 0; j < components; j++)
write[i * components + j] = read[re_ref[i] * components + j];
}else
for(j = 0; j < components; j++)
write[i * components + j] = 0;
}
free(read);
}
break;
}
}
void hxa_util_triangulate_node(HXANode *node, unsigned int max_sides)
{
unsigned int i, j, poly_count, ref_count, sides, *corner_reference, *poly_reference, count;
double *vertex;
float *vertex_f = NULL;
int *ref, *new_ref;
if(node->type != HXA_NT_GEOMETRY)
return;
if(node->content.geometry.vertex_stack.layers[0].type == HXA_LDT_FLOAT)
{
vertex_f = node->content.geometry.vertex_stack.layers[0].data.float_data;
count = node->content.geometry.vertex_count * 3;
vertex = malloc((sizeof *vertex) * count);
for(i = 0; i < count; i++)
vertex[i] = (double)vertex_f[i];
}else
vertex = node->content.geometry.vertex_stack.layers[0].data.double_data;
ref = node->content.geometry.corner_stack.layers[0].data.int32_data;
poly_count = ref_count = 0;
for(i = 0; i < node->content.geometry.edge_corner_count; i += sides)
{
for(sides = 0; ref[i + sides] >= 0; sides++);
if(sides > max_sides)
{
poly_count += sides + 1 - 3;
ref_count += (sides + 1 - 3) * 3;
}else
{
poly_count++;
ref_count += sides;
}
}
corner_reference = malloc((sizeof *corner_reference) * ref_count);
new_ref = malloc((sizeof *new_ref) * ref_count);
poly_reference = malloc((sizeof *poly_reference) * poly_count);
poly_count = ref_count = 0;
count = node->content.geometry.vertex_count;
for(i = 0; i < node->content.geometry.edge_corner_count; i += sides)
{
for(sides = 0; ref[i + sides] >= 0; sides++);
if(sides > max_sides)
{
hxa_util_triangulate_ngon(&ref[i], &new_ref[ref_count], &corner_reference[ref_count], i, sides, vertex, count);
ref_count += (sides + 1 - 3) * 3;
for(j = max_sides - 1; j < sides; j++)
poly_reference[poly_count++] = i;
}else
{
for(j = 0; j < sides; j++)
{
new_ref[ref_count] = ref[i + j];
corner_reference[ref_count++] = i + j;
}
poly_reference[poly_count++] = i;
}
}
node->content.geometry.corner_stack.layers[0].data.int32_data = new_ref;
for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++)
hxa_util_triangulate_re_ref_layer(&node->content.geometry.corner_stack.layers[i], ref_count, corner_reference);
for(i = 0; i < node->content.geometry.edge_stack.layer_count; i++)
hxa_util_triangulate_re_ref_edge_layer(&node->content.geometry.corner_stack.layers[i], ref_count, new_ref, ref, corner_reference);
for(i = 0; i < node->content.geometry.face_stack.layer_count; i++)
hxa_util_triangulate_re_ref_layer(&node->content.geometry.face_stack.layers[i], ref_count, poly_reference);
free(ref);
free(corner_reference);
free(poly_reference);
if(vertex_f != NULL)
free(vertex);
}

155
hxa_util_validate.c Normal file
View File

@ -0,0 +1,155 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
int hxa_util_validate_meta(HXAMeta *meta, unsigned int node, unsigned int count, int silent)
{
unsigned int i;
if(meta->type == HXA_MDT_NODE)
{
for(i = 0; meta->array_length; i++)
{
if(meta->value.node_value[i] >= count)
{
if(!silent)
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);
return FALSE;
}
}
}
if(meta->type == HXA_MDT_META)
for(i = 0; meta->array_length; i++)
if(!hxa_util_validate_meta(&((HXAMeta *)meta->value.node_value)[i], node, count, silent))
return FALSE;
return TRUE;
}
int hxa_util_validate(HXAFile *file, int silent)
{
char *layer_type_names[4] = {"HXA_LDT_UINT8", "HXA_LDT_INT32", "HXA_LDT_FLOAT", "HXA_LDT_DOUBLE"}, *test;
unsigned int i, j, poly_count, reference;
int *ref;
HXANode *node;
node = file->node_array;
for(i = 0; i < file->node_count; i++)
{
for(i = 0; i < node->meta_data_count; i++)
if(!hxa_util_validate_meta(&node->meta_data[i], i, file->node_count, silent))
return FALSE;
switch(node->type)
{
case HXA_NT_META_ONLY :
break;
case HXA_NT_GEOMETRY :
if(node->content.geometry.vertex_stack.layer_count == 0)
{
if(!silent)
printf("HxA Verify Error: Node %u has no vertex layer\n", i);
return FALSE;
}
if(node->content.geometry.vertex_stack.layers[0].components != 3)
{
if(!silent)
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);
return FALSE;
}
if(node->content.geometry.vertex_stack.layers[0].type != HXA_LDT_FLOAT &&
node->content.geometry.vertex_stack.layers[0].type != HXA_LDT_DOUBLE)
{
if(!silent)
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]);
return FALSE;
}
test = HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME;
for(j = 0; test[j] != 0 && node->content.geometry.vertex_stack.layers[0].name[j] != test[j]; j++);
if(node->content.geometry.vertex_stack.layers[0].name[j] != test[j])
{
if(!silent)
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);
return FALSE;
}
if(node->content.geometry.corner_stack.layer_count != 0)
{
if(node->content.geometry.corner_stack.layers[0].components != 1)
{
if(!silent)
printf("HxA Verify Error: Node %u reference layer has %u compinents. Must be 1.\n", i, node->content.geometry.corner_stack.layers[0].components);
return FALSE;
}
if(node->content.geometry.corner_stack.layers[0].type != HXA_LDT_INT32)
{
if(!silent)
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]);
return FALSE;
}
test = HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME;
for(j = 0; test[j] != 0 && node->content.geometry.corner_stack.layers[0].name[j] != test[j]; j++);
if(node->content.geometry.corner_stack.layers[0].name[j] != test[j])
{
if(!silent)
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);
return FALSE;
}
ref = node->content.geometry.corner_stack.layers[0].data.int32_data;
for(j = poly_count = 0; j < node->content.geometry.edge_corner_count; j++)
{
if(ref[j] < 0)
{
reference = -ref[j] - 1;
poly_count++;
}else
reference = ref[j];
if(reference >= node->content.geometry.vertex_count)
{
if(!silent)
printf("HxA Verify Error: Node %u has a reference value referencing a non existing vertex (%u).\n", i, reference);
return FALSE;
}
}
if(node->content.geometry.face_count != poly_count)
{
if(!silent)
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);
return FALSE;
}
}
break;
case HXA_NT_IMAGE :
break;
}
node++;
}
return TRUE;
}
int hxa_util_validate_pow(HXAFile *file, int silent)
{
unsigned int i, j, k, dim, success = TRUE;
for(i = 0; i < file->node_count; i++)
{
if(file->node_array[i].type == HXA_NT_IMAGE)
{
dim = file->node_array[i].content.image.type;
if(dim == HXA_IT_CUBE_IMAGE)
dim = 2;
for(j = 0; j < dim; j++)
{
for(k = 1; k < file->node_array[i].content.image.resolution[j]; k *= 2);
if(k > file->node_array[i].content.image.resolution[j])
{
if(!silent)
printf("HxA Verify Error: Node has non power of two resolution (%u)\n", file->node_array[i].content.image.resolution[j]);
success = FALSE;
}
}
}
}
return success;
}

70
hxa_util_vertex_purge.c Normal file
View File

@ -0,0 +1,70 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "hxa.h"
#include "hxa_utils.h"
#define FALSE 0
#define TRUE !FALSE
void hxa_util_node_vertex_purge(HXANode *node)
{
unsigned int type_size[] = {sizeof(hxa_uint8), sizeof(hxa_int32), sizeof(float), sizeof(double)};
unsigned int i, j, new_vertex_length, unit_size;
HXALayer *layer, l;
hxa_uint8 *new_buffer;
int r, *remap;
if(node->type != HXA_NT_GEOMETRY)
return;
remap = malloc((sizeof *remap) * node->content.geometry.vertex_count);
for(i = 0; i < node->content.geometry.vertex_count; i++)
remap[i] = 0;
layer = node->content.geometry.corner_stack.layers;
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
{
r = layer->data.int32_data[i];
if(r < 0)
r = -1 - r;
remap[r] = 1;
}
for(new_vertex_length = i = 0; i < node->content.geometry.vertex_count; i++)
if(remap[i])
new_vertex_length++;
if(node->content.geometry.vertex_count == new_vertex_length)
{
free(remap);
return;
}
for(i = 0; i < node->content.geometry.vertex_stack.layer_count; i++)
{
layer = &node->content.geometry.vertex_stack.layers[i];
unit_size = type_size[layer->type] * layer->components;
new_buffer = malloc(unit_size * new_vertex_length);
for(j = new_vertex_length = 0; j < node->content.geometry.vertex_count; j++)
if(remap[j])
memcpy(&new_buffer[new_vertex_length++ * unit_size], &layer->data.uint8_data[j * unit_size], unit_size);
free(layer->data.uint8_data);
layer->data.uint8_data = new_buffer;
}
node->content.geometry.vertex_count = new_vertex_length;
for(j = new_vertex_length = 0; j < node->content.geometry.vertex_count; j++)
if(remap[j])
remap[j] = new_vertex_length++;
layer = node->content.geometry.corner_stack.layers;
for(i = 0; i < node->content.geometry.edge_corner_count; i++)
{
r = layer->data.int32_data[i];
if(r < 0)
layer->data.int32_data[i] = -remap[-layer->data.int32_data[i] - 1] - 1;
else
layer->data.int32_data[i] = remap[layer->data.int32_data[i]];
}
}
void hxa_util_vertex_purge(HXAFile *file)
{
unsigned int i;
for(i = 0; i < file->node_count; i++)
hxa_util_node_vertex_purge(&file->node_array[i]);
}

View File

@ -3,6 +3,40 @@
extern HXAFile *hxa_load(char *file_name, int silent);
extern int hxa_save(char *file_name, HXAFile *data);
extern void hxa_print(HXAFile *file, int data);
extern void hxa_util_free_node_content(HXANode *node);
extern void hxa_util_free_file(HXAFile *file);
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);
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);
extern void *hxa_util_meta_get(HXAMeta *meta_data, hxa_uint32 meta_data_count, char *name, HXAMetaDataType type, unsigned int *length, int recursive);
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(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);
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 HXAFile *hxa_util_merge(HXAFile *file_a, HXAFile *file_b);
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_triangulate_node(HXANode *node, unsigned int max_sides);
extern void hxa_close_node(HXANode *node);
extern void hxa_close_file(HXAFile *file);