mirror of
https://github.com/quelsolaar/HxA
synced 2025-02-01 09:58:42 -05:00
511 lines
18 KiB
C
511 lines
18 KiB
C
#define _CRT_SECURE_NO_WARNINGS
|
|
#pragma warning(disable:4996)
|
|
#pragma warning(disable:4703)
|
|
#pragma warning(disable:4996)
|
|
#pragma warning(disable:4664)
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "hxa.h"
|
|
|
|
#define FALSE 0
|
|
#define TRUE !FALSE
|
|
|
|
|
|
double hxa_util_parce_floating_point(char *text, size_t *position)
|
|
{
|
|
double out = 0, mult = 0.1;
|
|
int neg = FALSE;
|
|
size_t i;
|
|
for(i = *position; (text[i] < '0' || text[i] < '0') && text[i] != '\n' && text[i] != 0 && text[i] != '-'; i++);
|
|
if(text[i] == 0 || text[i] == '\n')
|
|
{
|
|
*position = i;
|
|
return out;
|
|
}
|
|
if(text[i] == '-')
|
|
{
|
|
neg = TRUE;
|
|
}
|
|
while(text[i] >= '0' && text[i] <= '9')
|
|
{
|
|
out *= 10;
|
|
out += text[i++] - '0';
|
|
}
|
|
if(text[i] == '.')
|
|
{
|
|
i++;
|
|
while(text[i] >= '0' && text[i] <= '9')
|
|
{
|
|
out += mult * (double)(text[i++] - '0');
|
|
mult *= 0.1;
|
|
}
|
|
}
|
|
if(neg)
|
|
out = -out;
|
|
*position = i;
|
|
return out;
|
|
}
|
|
|
|
|
|
hxa_int32 hxa_util_parce_integer(char *text, size_t *position)
|
|
{
|
|
hxa_int32 out = 0, neg = FALSE;
|
|
size_t i;
|
|
for(i = *position; (text[i] < '0' || text[i] < '0') && text[i] != '\n' && text[i] != 0 && text[i] != '-'; i++);
|
|
if(text[i] == 0 || text[i] == '\n')
|
|
{
|
|
*position = i;
|
|
return out;
|
|
}
|
|
if(text[i] == '-')
|
|
{
|
|
neg = TRUE;
|
|
}
|
|
while(text[i] >= '0' && text[i] <= '9')
|
|
{
|
|
out *= 10;
|
|
out += text[i++] - '0';
|
|
}
|
|
if(neg)
|
|
out = -out;
|
|
*position = i;
|
|
return out;
|
|
}
|
|
|
|
|
|
char *hxa_util_obj_file_load(char *file_name, size_t *size)
|
|
{
|
|
char *buffer;
|
|
unsigned int allocation;
|
|
FILE *f;
|
|
f = fopen(file_name, "rb");
|
|
if(f == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
fseek(f, 0, SEEK_END);
|
|
allocation = ftell(f);
|
|
rewind(f);
|
|
buffer = malloc(allocation + 3);
|
|
buffer[0] = '\n'; /**/
|
|
allocation = fread(&buffer[1], 1, allocation, f) + 1;
|
|
buffer[allocation] = '\n';
|
|
buffer[allocation + 1] = 0;
|
|
fclose(f);
|
|
if(size != NULL)
|
|
*size = allocation;
|
|
return buffer;
|
|
}
|
|
|
|
HXANode *hxa_util_obj_add(HXAFile *file)
|
|
{
|
|
HXANode *node;
|
|
file->node_array = realloc(file->node_array, (sizeof *file->node_array) * (file->node_count + 1));
|
|
node = &file->node_array[file->node_count++];
|
|
node->type = HXA_NT_GEOMETRY;
|
|
node->meta_data_count = 0;
|
|
node->meta_data = NULL;
|
|
node->content.geometry.vertex_count = 0;
|
|
node->content.geometry.vertex_stack.layer_count = 0;
|
|
node->content.geometry.vertex_stack.layers = NULL;
|
|
node->content.geometry.edge_corner_count = 0;
|
|
node->content.geometry.corner_stack.layer_count = 0;
|
|
node->content.geometry.corner_stack.layers = NULL;
|
|
node->content.geometry.edge_stack.layer_count = 0;
|
|
node->content.geometry.edge_stack.layers = NULL;
|
|
node->content.geometry.face_count = 0;
|
|
node->content.geometry.face_stack.layer_count = 0;
|
|
node->content.geometry.face_stack.layers = NULL;
|
|
return node;
|
|
}
|
|
|
|
void hxa_util_obj_load_layer_set(HXALayer *layer, unsigned int count, HXALayerDataType type, unsigned char components, char *name)
|
|
{
|
|
unsigned int i;
|
|
layer->components = components;
|
|
layer->type = type;
|
|
if(type == HXA_LDT_INT32)
|
|
layer->data.int32_data = malloc((sizeof *layer->data.int32_data) * count * (unsigned int)components);
|
|
else if(type == HXA_LDT_FLOAT)
|
|
layer->data.float_data = malloc((sizeof *layer->data.float_data) * count * (unsigned int)components);
|
|
else if(type == HXA_LDT_DOUBLE)
|
|
layer->data.double_data = malloc((sizeof *layer->data.double_data) * count * (unsigned int)components);
|
|
else
|
|
layer->data.double_data = NULL;
|
|
for(i = 0; name[i] != 0; i++)
|
|
layer->name[i] = name[i];
|
|
layer->name[i] = 0;
|
|
}
|
|
|
|
void hxa_util_obj_build_vertex(HXANode *node, unsigned int vertex_count, unsigned int *used, double *vertex_array, unsigned int vertex_used)
|
|
{
|
|
unsigned int i;
|
|
double *v;
|
|
node->content.geometry.vertex_count = vertex_used;
|
|
v = node->content.geometry.vertex_stack.layers[0].data.double_data = malloc((sizeof *node->content.geometry.vertex_stack.layers[0].data.double_data) * 3 * vertex_used);
|
|
for(i = 0; i < vertex_count; i++)
|
|
{
|
|
if(used[i] != -1)
|
|
{
|
|
*v++ = vertex_array[i * 3 + 0];
|
|
*v++ = vertex_array[i * 3 + 1];
|
|
*v++ = vertex_array[i * 3 + 2];
|
|
used[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
void hxa_util_obj_layers_get(HXANode *node, hxa_int32 **mat, hxa_int32 **group, hxa_int32 **ref, float **uv, float **n)
|
|
{
|
|
char *group_name = HXA_CONVENTION_SOFT_LAYER_GROUP_ID, *material_name = HXA_CONVENTION_SOFT_LAYER_MATERIAL_ID, *uv_name = HXA_CONVENTION_SOFT_LAYER_UV0, *normals_name = HXA_CONVENTION_SOFT_LAYER_NORMALS;
|
|
unsigned int i, j;
|
|
node->content.geometry.edge_corner_count = 0;
|
|
node->content.geometry.face_count = 0;
|
|
*mat = NULL;
|
|
*group = NULL;
|
|
for(i = 0; i < node->content.geometry.face_stack.layer_count; i++)
|
|
{
|
|
for(j = 0; group_name[j] != 0 && node->content.geometry.face_stack.layers[i].name[j] == group_name[j]; j++);
|
|
if(node->content.geometry.face_stack.layers[i].name[j] == group_name[j])
|
|
*group = node->content.geometry.face_stack.layers[i].data.int32_data;
|
|
for(j = 0; material_name[j] != 0 && node->content.geometry.face_stack.layers[i].name[j] == material_name[j]; j++);
|
|
if(node->content.geometry.face_stack.layers[i].name[j] == material_name[j])
|
|
*mat = node->content.geometry.face_stack.layers[i].data.int32_data;
|
|
}
|
|
|
|
*ref = node->content.geometry.corner_stack.layers[HXA_CONVENTION_HARD_BASE_CORNER_LAYER_ID].data.int32_data;
|
|
*uv = *n = NULL;
|
|
for(i = 1; i < node->content.geometry.corner_stack.layer_count; i++)
|
|
{
|
|
for(j = 0; uv_name[j] != 0 && node->content.geometry.corner_stack.layers[i].name[j] == uv_name[j]; j++);
|
|
if(node->content.geometry.corner_stack.layers[i].name[j] == uv_name[j])
|
|
*uv = node->content.geometry.corner_stack.layers[i].data.float_data;
|
|
for(j = 0; normals_name[j] != 0 && node->content.geometry.corner_stack.layers[i].name[j] == normals_name[j]; j++);
|
|
if(node->content.geometry.corner_stack.layers[i].name[j] == normals_name[j])
|
|
*n = node->content.geometry.corner_stack.layers[i].data.float_data;
|
|
}
|
|
}
|
|
|
|
HXAFile *hxa_util_obj_load(char *file_name)
|
|
{
|
|
char *buffer;
|
|
HXAFile *file;
|
|
HXANode *node;
|
|
size_t i, j, temp, size;
|
|
double f, *vertex = NULL;
|
|
unsigned int white_space, slash_count, coord_count, normal_count, *used, primitive, vertex_used;
|
|
hxa_int32 r, *write_mat, *write_group, *write_ref, current_mat = 0, current_group = 0, vertex_count;
|
|
float *write_uv, *write_normals, *uv = NULL, *normals = NULL;
|
|
HXALayer *layer;
|
|
char *t;
|
|
buffer = hxa_util_obj_file_load(file_name, &size);
|
|
if(buffer == NULL)
|
|
return NULL;
|
|
size--;
|
|
file = malloc(sizeof *file);
|
|
file->node_count = 0;
|
|
file->node_array = malloc(sizeof *file->node_array);
|
|
node = hxa_util_obj_add(file);
|
|
vertex_count = coord_count = normal_count = 0;
|
|
for(i = 0; i < size; i++)
|
|
{
|
|
if(buffer[i] == '\n')
|
|
{
|
|
i++;
|
|
if(buffer[i] == 'g' && buffer[i + 1] <= ' ') /* new objects */
|
|
{
|
|
if(node->content.geometry.face_count != 0)
|
|
node = hxa_util_obj_add(file);
|
|
}
|
|
if(buffer[i] == 'f' && buffer[i + 1] <= ' ') /* we have faces */
|
|
{
|
|
white_space = TRUE;
|
|
j = slash_count = 0;
|
|
do {
|
|
i++;
|
|
if(buffer[i] == '/')
|
|
{
|
|
if(buffer[i + 1] == '/')
|
|
{
|
|
node->content.geometry.vertex_count |= 1;/* borrow vertex count to store use of vertex normals*/
|
|
slash_count = 42;
|
|
}else
|
|
slash_count++;
|
|
}
|
|
|
|
if(white_space != (buffer[i] <= ' '))
|
|
{
|
|
if(white_space)
|
|
node->content.geometry.edge_corner_count++;
|
|
if(slash_count == 1)
|
|
node->content.geometry.vertex_count |= 2; /* borrow vertex count to store use of vertex coordinates*/
|
|
else if(slash_count == 2)
|
|
node->content.geometry.vertex_count |= 3; /* borrow vertex count to store use of vertex coordinates ad normals*/
|
|
slash_count = 0;
|
|
white_space = !white_space;
|
|
j++;
|
|
}
|
|
}while(buffer[i] != '\n');
|
|
node->content.geometry.edge_corner_count += j / 2;
|
|
node->content.geometry.face_count++;
|
|
}
|
|
if(buffer[i] == 's' && buffer[i + 1] <= ' ') /* we have groups */
|
|
{
|
|
node->content.geometry.face_stack.layer_count |= 1;
|
|
}
|
|
if(buffer[i] == 'u' && buffer[i + 1] == 's' && buffer[i + 2] == 'e' && buffer[i + 3] == 'm' && buffer[i + 4] == 't' && buffer[i + 5] == 'l' && buffer[i + 6] <= ' ') /* we have groups */
|
|
{
|
|
node->content.geometry.face_stack.layer_count |= 2;
|
|
}
|
|
if(buffer[i] == 'v') /* we have groups */
|
|
{
|
|
i++;
|
|
if(buffer[i] <= ' ')
|
|
vertex_count++;
|
|
else
|
|
{
|
|
if(buffer[i] == 't' && buffer[i + 1] <= ' ')
|
|
coord_count++;
|
|
else if(buffer[i] == 'n' && buffer[i + 1] <= ' ')
|
|
normal_count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(i = 0; i < file->node_count; i++)
|
|
{
|
|
/* face stack */
|
|
node = &file->node_array[i];
|
|
temp = node->content.geometry.face_stack.layer_count;
|
|
if(temp == (1 | 2))
|
|
node->content.geometry.face_stack.layers = malloc((sizeof *node->content.geometry.face_stack.layers) * 2);
|
|
else if(temp != 0)
|
|
node->content.geometry.face_stack.layers = malloc(sizeof *node->content.geometry.face_stack.layers);
|
|
node->content.geometry.face_stack.layer_count = 0;
|
|
if(temp & 1)
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.face_stack.layers[node->content.geometry.face_stack.layer_count++], node->content.geometry.face_count, HXA_LDT_INT32, 1, HXA_CONVENTION_SOFT_LAYER_GROUP_ID);
|
|
if(temp & 2)
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.face_stack.layers[node->content.geometry.face_stack.layer_count++], node->content.geometry.face_count, HXA_LDT_INT32, 1, HXA_CONVENTION_SOFT_LAYER_MATERIAL_ID);
|
|
/* vertex stack */
|
|
node->content.geometry.vertex_stack.layers = malloc(sizeof *node->content.geometry.vertex_stack.layers);
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.vertex_stack.layers[node->content.geometry.vertex_stack.layer_count++], 0, HXA_LDT_DOUBLE, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_COMPONENTS, HXA_CONVENTION_HARD_BASE_VERTEX_LAYER_NAME);
|
|
|
|
/* corner stack */
|
|
node->content.geometry.corner_stack.layer_count = 1;
|
|
if((node->content.geometry.vertex_count & 1) && normal_count != 0)
|
|
node->content.geometry.corner_stack.layer_count++;
|
|
if((node->content.geometry.vertex_count & 2) && coord_count != 0)
|
|
node->content.geometry.corner_stack.layer_count++;
|
|
node->content.geometry.corner_stack.layers = malloc((sizeof *node->content.geometry.corner_stack.layers) * node->content.geometry.corner_stack.layer_count);
|
|
node->content.geometry.corner_stack.layer_count = 0;
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.corner_stack.layers[node->content.geometry.corner_stack.layer_count++], node->content.geometry.edge_corner_count, HXA_LDT_INT32, HXA_CONVENTION_HARD_BASE_CORNER_LAYER_COMPONENTS, HXA_CONVENTION_HARD_BASE_CORNER_LAYER_NAME);
|
|
if((node->content.geometry.vertex_count & 1) && normal_count != 0)
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.corner_stack.layers[node->content.geometry.corner_stack.layer_count++], node->content.geometry.edge_corner_count, HXA_LDT_FLOAT, 3, HXA_CONVENTION_SOFT_LAYER_NORMALS);
|
|
if((node->content.geometry.vertex_count & 2) && coord_count != 0)
|
|
hxa_util_obj_load_layer_set(&node->content.geometry.corner_stack.layers[node->content.geometry.corner_stack.layer_count++], node->content.geometry.edge_corner_count, HXA_LDT_FLOAT, 2, HXA_CONVENTION_SOFT_LAYER_UV0);
|
|
node->content.geometry.face_count = 0;
|
|
}
|
|
vertex = malloc((sizeof *vertex) * vertex_count * 3);
|
|
if(coord_count != 0)
|
|
uv = malloc((sizeof *uv) * coord_count * 2);
|
|
if(normal_count != 0)
|
|
normals = malloc((sizeof *normals) * normal_count * 3);
|
|
vertex_count = coord_count = normal_count = 0;
|
|
for(i = 0; i < size; i++)
|
|
{
|
|
if(buffer[i] == '\n')
|
|
{
|
|
i++;
|
|
if(buffer[i] == 'v') /* we have groups */
|
|
{
|
|
i++;
|
|
if(buffer[i] <= ' ')
|
|
{
|
|
vertex[vertex_count * 3] = vertex[vertex_count * 3 + 1] = vertex[vertex_count * 3 + 2] = 0.0;
|
|
vertex[vertex_count * 3] = hxa_util_parce_floating_point(buffer, &i);
|
|
if(buffer[i] != 0 && buffer[i] != 0)
|
|
{
|
|
vertex[vertex_count * 3 + 1] = hxa_util_parce_floating_point(buffer, &i);
|
|
if(buffer[i] != 0 && buffer[i] != 0)
|
|
vertex[vertex_count * 3 + 2] = hxa_util_parce_floating_point(buffer, &i);
|
|
}
|
|
i--;
|
|
vertex_count++;
|
|
}
|
|
else if(buffer[i] == 't' && buffer[i + 1] <= ' ')
|
|
{
|
|
uv[coord_count * 2] = uv[coord_count * 2 + 1] = 0.0;
|
|
uv[coord_count * 2] = hxa_util_parce_floating_point(buffer, &i);
|
|
if(buffer[i] != 0 && buffer[i] != 0)
|
|
uv[coord_count * 2 + 1] = hxa_util_parce_floating_point(buffer, &i);
|
|
i--;
|
|
coord_count++;
|
|
}
|
|
else if(buffer[i] == 'n' && buffer[i + 1] <= ' ')
|
|
{
|
|
normals[normal_count * 3] = normals[normal_count * 3 + 1] = normals[normal_count * 3 + 2] = 1.0;
|
|
normals[normal_count * 3] = hxa_util_parce_floating_point(buffer, &i);
|
|
if(buffer[i] != 0 && buffer[i] != 0)
|
|
{
|
|
normals[normal_count * 3 + 1] = hxa_util_parce_floating_point(buffer, &i);
|
|
if(buffer[i] != 0 && buffer[i] != 0)
|
|
normals[normal_count * 3 + 2] = hxa_util_parce_floating_point(buffer, &i);
|
|
}
|
|
i--;
|
|
f = sqrt(normals[normal_count * 3] * normals[normal_count * 3] +
|
|
normals[normal_count * 3 + 1] * normals[normal_count * 3 + 1] +
|
|
normals[normal_count * 3 + 2] * normals[normal_count * 3 + 2]);
|
|
if(f > 0.0001)
|
|
{
|
|
normals[normal_count * 3] /= f;
|
|
normals[normal_count * 3 + 1] /= f;
|
|
normals[normal_count * 3 + 2] /= f;
|
|
}else
|
|
{
|
|
normals[normal_count * 3] = normals[normal_count * 3 + 1] = 0.0;
|
|
normals[normal_count * 3 + 2] = 1.0;
|
|
}
|
|
normal_count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
used = malloc((sizeof *used) * vertex_count);
|
|
for(i = 0; i < vertex_count; i++)
|
|
used[i] = -1;
|
|
node = file->node_array;
|
|
file->node_count = 0;
|
|
hxa_util_obj_layers_get(node, &write_mat, &write_group, &write_ref, &write_uv, &write_normals);
|
|
|
|
vertex_used = 0;
|
|
for(i = 0; i < size; i++)
|
|
{
|
|
if(buffer[i] == '\n')
|
|
{
|
|
i++;
|
|
if(buffer[i] == 'g' && buffer[i + 1] <= ' ')
|
|
{
|
|
f_debug_memory();
|
|
if(node->content.geometry.face_count != 0)
|
|
{
|
|
hxa_util_obj_build_vertex(node, vertex_count, used, vertex, vertex_used);
|
|
vertex_used = 0;
|
|
|
|
file->node_count++;
|
|
node++;
|
|
}
|
|
hxa_util_obj_layers_get(node, &write_mat, &write_group, &write_ref, &write_uv, &write_normals);
|
|
for(i++; buffer[i] <= ' ' && buffer[i] != '\n'; i++);
|
|
if(buffer[i] != '\n')
|
|
{
|
|
char *name = HXA_CONVENTION_SOFT_NAME;
|
|
node->meta_data = realloc(node->meta_data, sizeof *node->meta_data);
|
|
for(j = 0; j < HXA_NAME_MAX_LENGTH && name[j] != 0; j++)
|
|
node->meta_data[0].name[j] = name[j];
|
|
node->meta_data[0].name[j] = 0;
|
|
node->meta_data[0].type = HXA_MDT_TEXT;
|
|
for(j = 0; buffer[i + j] != 0 && buffer[i + j] != '\n'; j++);
|
|
node->meta_data[0].array_length = j;
|
|
node->meta_data[0].value.text_value = malloc(node->meta_data[0].array_length + 1);
|
|
for(j = 0; j < node->meta_data[0].array_length; j++)
|
|
node->meta_data[0].value.text_value[j] = buffer[i + j];
|
|
node->meta_data[0].value.text_value[j] = 0;
|
|
printf("-%s-\n", node->meta_data[0].value.text_value);
|
|
node->meta_data_count = 1;
|
|
}
|
|
f_debug_memory();
|
|
}else if(buffer[i] == 'f')
|
|
{
|
|
i++;
|
|
primitive = 0;
|
|
while(buffer[i] != '\n' && buffer[i] != 0)
|
|
{
|
|
if(buffer[i] >= '0' && buffer[i] <= '9')
|
|
{
|
|
r = hxa_util_parce_integer(buffer, &i) - 1;
|
|
if(r < vertex_count && r >= 0)
|
|
{
|
|
if(used[r] == -1)
|
|
used[r] = vertex_used++;
|
|
write_ref[primitive] = used[r];
|
|
if(buffer[i] == '/')
|
|
{
|
|
r = hxa_util_parce_integer(buffer, &i) - 1;
|
|
if(r < coord_count && r >= 0 && write_uv != NULL)
|
|
{
|
|
write_uv[primitive * 2] = uv[r * 2];
|
|
write_uv[primitive * 2 + 1] = uv[r * 2 + 1];
|
|
}
|
|
if(buffer[i] == '/')
|
|
{
|
|
r = hxa_util_parce_integer(buffer, &i);
|
|
if(r < normal_count && r >= 0 && write_normals != NULL)
|
|
{
|
|
write_normals[primitive * 3] = normals[r * 3];
|
|
write_normals[primitive * 3 + 1] = normals[r * 3 + 1];
|
|
write_normals[primitive * 3 + 2] = normals[r * 3 + 2];
|
|
}
|
|
}
|
|
}
|
|
primitive++;
|
|
}
|
|
}else
|
|
i++;
|
|
f_debug_memory();
|
|
}
|
|
if(primitive > 2)
|
|
{
|
|
f_debug_memory();
|
|
write_ref[primitive - 1] = -1 - write_ref[primitive - 1];
|
|
write_ref += primitive;
|
|
node->content.geometry.edge_corner_count += primitive;
|
|
if(write_uv != NULL)
|
|
write_uv += primitive * 2;
|
|
if(write_normals != NULL)
|
|
write_normals += primitive * 3;
|
|
f_debug_memory();
|
|
if(write_mat != NULL)
|
|
write_mat[node->content.geometry.face_count] = current_mat;
|
|
f_debug_memory();
|
|
if(write_group != NULL)
|
|
write_group[node->content.geometry.face_count] = current_group;
|
|
node->content.geometry.face_count++;
|
|
f_debug_memory();
|
|
|
|
}
|
|
}else if(buffer[i] == 's' && buffer[i + 1] <= ' ') /* we have groups */
|
|
{
|
|
current_group = hxa_util_parce_integer(buffer, &i);
|
|
i--;
|
|
}else if(buffer[i] == 'u' && buffer[i + 1] == 's' && buffer[i + 2] == 'e' && buffer[i + 3] == 'm' && buffer[i + 4] == 't' && buffer[i + 5] == 'l' && buffer[i + 6] <= ' ') /* we have groups */
|
|
{
|
|
current_mat = hxa_util_parce_integer(buffer, &i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
if(node->content.geometry.face_count != 0)
|
|
{
|
|
hxa_util_obj_build_vertex(node, vertex_count, used, vertex, vertex_used);
|
|
file->node_count++;
|
|
}
|
|
if(vertex != 0)
|
|
free(vertex);
|
|
if(uv != 0)
|
|
free(uv);
|
|
if(normals != 0)
|
|
free(normals);
|
|
free(buffer);
|
|
return file;
|
|
}
|
|
|
|
/*
|
|
void hxa_print(HXAFile *file, int data);
|
|
|
|
int main(void)
|
|
{
|
|
HXAFile *file;
|
|
file = hxa_util_obj_load("object2.obj");
|
|
hxa_print(file, FALSE);
|
|
file = NULL;
|
|
}*/ |