QuelSolaar/vetk_verse_geo.c

877 lines
28 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "enough.h"
#include "vetk.h"
void vetk_compute_neighbor(ENode *node, VETKQuadTri *poly)
{
uint i, cor, clear = 0, *n, *v, a, b, *ref;
uint counter = 0, laps = 0, vertex_count;
ref = poly->ref;
vertex_count = e_nsg_get_vertex_length(node);
n = malloc((sizeof *n) * (poly->quad_length + poly->tri_length));
for(i = 0; i < (poly->quad_length + poly->tri_length); i++)
n[i] = -1;
v = malloc((sizeof *v) * vertex_count);
for(i = 0; i < vertex_count; i++)
v[i] = -1;
while(clear < poly->quad_length + poly->tri_length)
{
for(i = 0; i < poly->quad_length && clear < poly->quad_length + poly->tri_length; i++)
{
counter++;
cor = v[ref[i]];
if(cor == -1)
{
if(n[i] == -1 || n[(i / 4) * 4 + (i + 3) % 4] == -1)
v[ref[i]] = i;
// else
// printf("jump!");
}
else if(cor == i)
v[ref[i]] = -1;
else
{
if(cor >= poly->quad_length)
{ /* other poly is a tri */
a = (i / 4) * 4;
b = poly->quad_length + ((cor - poly->quad_length) / 3) * 3;
if((n[cor] == -1 && n[a + (i + 3) % 4] == -1) && ref[a + (i + 3) % 4] == ref[b + (cor - b + 1) % 3])
{
n[a + (i + 3) % 4] = cor;
n[cor] = a + (i + 3) % 4;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[b + (cor - b + 2) % 3] != -1)
{
if(n[i] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
}
if((n[i] == -1 && n[b + (cor - b + 2) % 3] == -1) && ref[a + (i + 1) % 4] == ref[b + (cor - b + 2) % 3])
{
n[i] = b + (cor - b + 2) % 3;
n[b + (cor - b + 2) % 3] = i;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[cor] != -1)
{
if(n[a + (i + 3) % 4] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
// v[ref[i]] = -1;
}
}else
{
/* other poly is a quad */
a = (i / 4) * 4;
b = (cor / 4) * 4;
if((n[cor] == -1 && n[a + (i + 3) % 4] == -1) && ref[a + (i + 3) % 4] == ref[b + (cor + 1) % 4])
{
n[a + (i + 3) % 4] = cor;
n[cor] = a + (i + 3) % 4;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
// v[ref[i]] = -1;
if(n[b + (cor + 3) % 4] != -1)
{
if(n[i] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
}
if((n[i] == -1 && n[b + (cor + 3) % 4] == -1) && ref[a + (i + 1) % 4] == ref[b + (cor + 3) % 4])
{
n[i] = b + (cor + 3) % 4;
n[b + (cor + 3) % 4] = i;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[cor] != -1)
{
if(n[a + (i + 3) % 4] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
}
}
}
clear++;
}
for(; i < poly->quad_length + poly->tri_length && clear < poly->quad_length + poly->tri_length; i++)
{
cor = v[ref[i]];
if(cor == -1)
{
// if(ncor == -1)
v[ref[i]] = i;
}
else if(cor == i)
v[ref[i]] = -1;
else
{
if(cor >= poly->quad_length)
{ /* other poly is a tri */
a = poly->quad_length + ((i - poly->quad_length) / 3) * 3;
b = poly->quad_length + ((cor - poly->quad_length) / 3) * 3;
if((n[cor] == -1 && n[a + (i - a + 2) % 3] == -1) && ref[a + (i - a + 2) % 3] == ref[b + (cor - b + 1) % 3])
{
n[a + (i - a + 2) % 3] = cor;
n[cor] = a + (i - a + 2) % 3;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[b + (cor - b + 2) % 3] != -1)
{
if(n[i] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
// v[ref[i]] = -1;
}
if((n[i] == -1 && n[b + (cor - b + 2) % 3] == -1) && ref[a + (i - a + 1) % 3] == ref[b + (cor - b + 2) % 3])
{
n[i] = b + (cor - b + 2) % 3;
n[b + (cor - b + 2) % 3] = i;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[cor] != -1)
{
if(n[a + (i - a + 2) % 3] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
// v[ref[i]] = -1;
}
}else
{
/* other poly is a quad */
a = poly->quad_length + ((i - poly->quad_length) / 3) * 3;
b = (cor / 4) * 4;
if((n[cor] == -1 && n[a + (i - a + 2) % 3] == -1) && ref[a + (i - a + 2) % 3] == ref[b + (cor + 1) % 4])
{
n[a + (i - a + 2) % 3] = cor;
n[cor] = a + (i - a + 2) % 3;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[b + (cor + 3) % 4] != -1)
{
if(n[i] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
// v[ref[i]] = -1;
}
if((n[i] == -1 && n[(cor - b + 3) % 4] == -1) && ref[a + (i - a + 1) % 3] == ref[b + (cor + 3) % 4])
{
n[i] = b + (cor + 3) % 4;
n[b + (cor + 3) % 4] = i;
// printf("i = %u clear = %u\n", i, clear);
clear = 0;
if(n[cor] != -1)
{
if(n[a + (i - a + 2) % 3] == -1)
v[ref[i]] = i;
else
v[ref[i]] = -1;
}
// v[ref[i]] = -1;
}
}
}
counter++;
clear++;
}
laps++;
}
counter = 0;
free(v);
poly->neighbor = n;
}
void *vetk_get_vertex_param(ENode *node, VETKQuadTri *mesh, char **vertex_params, uint param_count, float *normal)
{
uint i, j, tri, quad, ref_count, vertex_count, *ref, axis;
egreal *vertex;
char *name, *n = "normal";
EGeoLayer *layer;
void *data;
void *output;
vertex_count = e_nsg_get_vertex_length(node);
ref_count = e_nsg_get_polygon_length(node) * 4;
vertex = e_nsg_get_layer_data(node, e_nsg_get_layer_by_id(node, 0));
ref = e_nsg_get_layer_data(node, e_nsg_get_layer_by_id(node, 1));
output = malloc(4 * (mesh->quad_length + mesh->tri_length) * param_count);
for(i = 0; i < param_count; i++)
{
axis = 0;
quad = 0;
tri = mesh->quad_length;
name = vertex_params[i];
if(name[1] == 46 && name[0] >= 120 && name[0] <= 122)
{
axis = name[0] - 120;
name = &name[2];
}
layer = e_nsg_get_layer_by_name(node, name);
data = e_nsg_get_layer_data(node, layer);
if(layer == NULL || data == NULL || (VN_G_LAYER_VERTEX_XYZ != e_nsg_get_layer_type(layer) && axis != 0))
{
for(j = 0; name[j] == n[j] && name[j] != 0; j++);
if(name[j] != 0)
{
for(j = 0; j < mesh->quad_length + mesh->tri_length; j++)
((float *)output)[j * param_count + i] = 0.0;
}else
{
for(j = 0; j < mesh->quad_length + mesh->tri_length; j++)
{
((float *)output)[j * param_count + i] = normal[j * 3 + axis];
}
}
}else
{
switch(e_nsg_get_layer_type(layer))
{
case VN_G_LAYER_VERTEX_XYZ :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 0] * 3 + axis];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 1] * 3 + axis];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 2] * 3 + axis];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 3] * 3 + axis];
}else
{
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 0] * 3 + axis];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 1] * 3 + axis];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 2] * 3 + axis];
}
}
}
break;
case VN_G_LAYER_VERTEX_UINT32 :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((uint32 *)output)[quad++ * param_count + i] = ((uint32 *)data)[ref[j + 0]];
((uint32 *)output)[quad++ * param_count + i] = ((uint32 *)data)[ref[j + 1]];
((uint32 *)output)[quad++ * param_count + i] = ((uint32 *)data)[ref[j + 2]];
((uint32 *)output)[quad++ * param_count + i] = ((uint32 *)data)[ref[j + 3]];
}else
{
((uint32 *)output)[tri++ * param_count + i] = ((uint32 *)data)[ref[j + 0]];
((uint32 *)output)[tri++ * param_count + i] = ((uint32 *)data)[ref[j + 1]];
((uint32 *)output)[tri++ * param_count + i] = ((uint32 *)data)[ref[j + 2]];
}
}
}
break;
case VN_G_LAYER_VERTEX_REAL :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 0]];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 1]];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 2]];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[ref[j + 3]];
}else
{
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 0]];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 1]];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[ref[j + 2]];
}
}
}
break;
case VN_G_LAYER_POLYGON_CORNER_UINT32 :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j + 0];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j + 1];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j + 2];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j + 3];
}else
{
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j + 0];
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j + 1];
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j + 2];
}
}
}
break;
case VN_G_LAYER_POLYGON_CORNER_REAL :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j + 0];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j + 1];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j + 2];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j + 3];
}else
{
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j + 0];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j + 1];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j + 2];
}
}
}
break;
case VN_G_LAYER_POLYGON_FACE_UINT8 :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((uint8 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint8 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint8 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint8 *)data)[j / 4];
}else
{
((float *)output)[tri++ * param_count + i] = ((uint8 *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((uint8 *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((uint8 *)data)[j / 4];
}
}
}
break;
case VN_G_LAYER_POLYGON_FACE_UINT32 :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((uint32 *)data)[j / 4];
}else
{
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((uint32 *)data)[j / 4];
}
}
}
break;
case VN_G_LAYER_POLYGON_FACE_REAL :
for(j = 0; j < ref_count; j += 4)
{
if(ref[j] < vertex_count && ref[j + 1] < vertex_count && ref[j + 2] < vertex_count && vertex[ref[j] * 3] != E_REAL_MAX && vertex[ref[j + 1] * 3] != E_REAL_MAX && vertex[ref[j + 2] * 3] != E_REAL_MAX)
{
if(ref[j + 3] < vertex_count && vertex[ref[j + 3] * 3] != E_REAL_MAX)
{
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j / 4];
((float *)output)[quad++ * param_count + i] = ((egreal *)data)[j / 4];
}else
{
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j / 4];
((float *)output)[tri++ * param_count + i] = ((egreal *)data)[j / 4];
}
}
}
break;
}
}
}
return output;
}
uint *vetk_poly_clean(ENode *node, VETKQuadTri *mesh, char **vertex_params, uint param_count)
{
uint *ref, *crease, vertex_count, ref_count, i, def,tri, quad;
egreal *vertex;
uint *c;
vertex = e_nsg_get_layer_data(node, e_nsg_get_layer_by_id(node, 0));
ref = e_nsg_get_layer_data(node, e_nsg_get_layer_by_id(node, 1));
crease = e_nsg_get_layer_data(node, e_nsg_get_layer_crease_edge_layer(node));
vertex_count = e_nsg_get_vertex_length(node);
ref_count = e_nsg_get_polygon_length(node) * 4;
mesh->quad_length = 0;
mesh->tri_length = 0;
for(i = 0; i < ref_count; i += 4)
{
if(ref[i] < vertex_count && ref[i + 1] < vertex_count && ref[i + 2] < vertex_count && vertex[ref[i] * 3] != E_REAL_MAX && vertex[ref[i + 1] * 3] != E_REAL_MAX && vertex[ref[i + 2] * 3] != E_REAL_MAX)
{
if(ref[i + 3] < vertex_count && vertex[ref[i + 3] * 3] != E_REAL_MAX)
mesh->quad_length += 4;
else
mesh->tri_length += 3;
}
}
if(mesh->quad_length + mesh->tri_length == 0)
return NULL;
mesh->ref = malloc((sizeof *mesh->ref) * (mesh->quad_length + mesh->tri_length));
c = malloc((sizeof *c) * (mesh->quad_length + mesh->tri_length));
tri = mesh->quad_length;
quad = 0;
if(crease == NULL)
{
def = e_nsg_get_layer_crease_edge_value(node);
for(i = 0; i < mesh->quad_length + mesh->tri_length; i++)
c[i] = def;
for(i = 0; i < ref_count; i += 4)
{
if(ref[i] < vertex_count && ref[i + 1] < vertex_count && ref[i + 2] < vertex_count && vertex[ref[i] * 3] != E_REAL_MAX && vertex[ref[i + 1] * 3] != E_REAL_MAX && vertex[ref[i + 2] * 3] != E_REAL_MAX)
{
if(ref[i + 3] < vertex_count && vertex[ref[i + 3] * 3] != E_REAL_MAX)
{
mesh->ref[quad++] = ref[i];
mesh->ref[quad++] = ref[i + 1];
mesh->ref[quad++] = ref[i + 2];
mesh->ref[quad++] = ref[i + 3];
}else
{
mesh->ref[tri++] = ref[i];
mesh->ref[tri++] = ref[i + 1];
mesh->ref[tri++] = ref[i + 2];
}
}
}
}else
{
for(i = 0; i < ref_count; i += 4)
{
if(ref[i] < vertex_count && ref[i + 1] < vertex_count && ref[i + 2] < vertex_count && vertex[ref[i] * 3] != E_REAL_MAX && vertex[ref[i + 1] * 3] != E_REAL_MAX && vertex[ref[i + 2] * 3] != E_REAL_MAX)
{
if(ref[i + 3] < vertex_count && vertex[ref[i + 3] * 3] != E_REAL_MAX)
{
mesh->ref[quad] = ref[i];
c[quad++] = crease[i];
mesh->ref[quad] = ref[i + 1];
c[quad++] = crease[i + 1];
mesh->ref[quad] = ref[i + 2];
c[quad++] = crease[i + 2];
mesh->ref[quad] = ref[i + 3];
c[quad++] = crease[i + 3];
}else
{
mesh->ref[tri] = ref[i];
c[tri++] = crease[i];
mesh->ref[tri] = ref[i + 1];
c[tri++] = crease[i + 1];
mesh->ref[tri] = ref[i + 2];
c[tri++] = crease[i + 2];
}
}
}
}
return c;
}
void vetk_vec_normalize(egreal *output, egreal *vec_a, egreal *vec_b)
{
egreal f;
output[0] = vec_a[0] - vec_b[0];
output[1] = vec_a[1] - vec_b[1];
output[2] = vec_a[2] - vec_b[2];
f = sqrt(output[0] * output[0] + output[1] * output[1] + output[2] * output[2]);
output[0] /= f;
output[1] /= f;
output[2] /= f;
}
void vetk_corner_normal_old(VETKQuadTri *mesh, float *corner_normal, float *poly_normal, uint first, uint *crease)
{
uint cur, p, next = -1;
egreal n[3], f;
next = first;
n[0] = 0;
n[1] = 0;
n[2] = 0;
while(TRUE)
{
cur = next;
if(cur > mesh->quad_length)
p = mesh->quad_length / 4 + (cur - mesh->quad_length) / 3;
else
p = cur / 4;
// printf("add %u - %f %f %f\n", p, poly_normal[p * 3 + 0], poly_normal[p * 3 + 1], poly_normal[p * 3 + 2]);
n[0] += poly_normal[p * 3 + 0];
n[1] += poly_normal[p * 3 + 1];
n[2] += poly_normal[p * 3 + 2];
if(crease[cur] > 2000000000 || mesh->neighbor[cur] == -1)
break;
cur = mesh->neighbor[cur];
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 1) % 3);
else
next = ((cur / 4) * 4) + ((cur + 1) % 4);
if(next == first)
break;
}
if(next != first)
{
if(crease[cur] < 2000000000 && mesh->neighbor[next] != -1)
{
cur = mesh->neighbor[next];
if(cur != -1)
{
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 3) % 3);
else
next = ((cur / 4) * 4) + ((cur + 2) % 4);
first = next;
while(TRUE)
{
cur = next;
if(cur > mesh->quad_length)
p = mesh->quad_length / 4 + (cur - mesh->quad_length) / 3;
else
p = cur / 4;
// printf("add %u - %f %f %f\n", p, poly_normal[p * 3 + 0], poly_normal[p * 3 + 1], poly_normal[p * 3 + 2]);
n[0] += poly_normal[p * 3 + 0];
n[1] += poly_normal[p * 3 + 1];
n[2] += poly_normal[p * 3 + 2];
if(crease[cur] > 2000000000 || mesh->neighbor[cur] == -1)
break;
cur = mesh->neighbor[cur];
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 3) % 3);
else
next = ((cur / 4) * 4) + ((cur + 2) % 4);
if(next == first)
break;
}
}
}
}
f = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
corner_normal[first * 3 + 0] = n[0] / f;
corner_normal[first * 3 + 1] = n[1] / f;
corner_normal[first * 3 + 2] = n[2] / f;
}
void vetk_corner_normal(VETKQuadTri *mesh, float *corner_normal, float *poly_normal, uint first, uint *crease)
{
uint cur, p, next = -1, counter = 0, break_out;
egreal n[3], f;
next = first;
n[0] = 0;
n[1] = 0;
n[2] = 0;
for(break_out = 0; break_out < 256; break_out++)
{
cur = next;
next = -1;
if(cur > mesh->quad_length)
p = mesh->quad_length / 4 + (cur - mesh->quad_length) / 3;
else
p = cur / 4;
n[0] += poly_normal[p * 3 + 0];
n[1] += poly_normal[p * 3 + 1];
n[2] += poly_normal[p * 3 + 2];
counter++;
if(crease[cur] > 2000000000 || mesh->neighbor[cur] == -1)
break;
cur = mesh->neighbor[cur];
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 1) % 3);
else
next = ((cur / 4) * 4) + ((cur + 1) % 4);
if(next == first)
break;
}
if(next != first)
{
cur = first;
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 2) % 3);
else
next = ((cur / 4) * 4) + ((cur + 3) % 4);
counter = 0;
if(crease[next] < 2000000000 && mesh->neighbor[next] != -1)
{
cur = mesh->neighbor[next];
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 2) % 3);
else
next = ((cur / 4) * 4) + ((cur + 3) % 4);
while(TRUE)
{
cur = next;
if(cur > mesh->quad_length)
p = mesh->quad_length / 4 + (cur - mesh->quad_length) / 3;
else
p = cur / 4;
n[0] += poly_normal[p * 3 + 0];
n[1] += poly_normal[p * 3 + 1];
n[2] += poly_normal[p * 3 + 2];
counter++;
if(crease[cur] > 2000000000 || mesh->neighbor[cur] == -1 || counter > 500)
break;
cur = mesh->neighbor[cur];
if(cur > mesh->quad_length)
next = mesh->quad_length + (((cur - mesh->quad_length) / 3) * 3) + (((cur - mesh->quad_length) + 2) % 3);
else
next = ((cur / 4) * 4) + ((cur + 3) % 4);
if(next == first)
break;
}
}
}
f = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
corner_normal[first * 3 + 0] = n[0] / f;
corner_normal[first * 3 + 1] = n[1] / f;
corner_normal[first * 3 + 2] = n[2] / f;
}
float *vetk_poly_normal(ENode *node, VETKQuadTri *mesh)
{
egreal *vertex, *v0, *v1, *v2, *v3, vec_a[3], vec_b[3], n[3], f;
float *normal;
uint i, j = 0;
vertex = e_nsg_get_layer_data(node, e_nsg_get_layer_by_id(node, 0));
normal = malloc((sizeof *normal) * (mesh->quad_length / 4 + mesh->tri_length / 3) * 3);
for(i = 0; i < mesh->quad_length; i += 4)
{
v0 = &vertex[mesh->ref[i] * 3];
v1 = &vertex[mesh->ref[i + 1] * 3];
v2 = &vertex[mesh->ref[i + 2] * 3];
v3 = &vertex[mesh->ref[i + 3] * 3];
vetk_vec_normalize(vec_a, v0, v3);
vetk_vec_normalize(vec_b, v0, v1);
n[0] = vec_a[1] * vec_b[2] - vec_a[2] * vec_b[1];
n[1] = vec_a[2] * vec_b[0] - vec_a[0] * vec_b[2];
n[2] = vec_a[0] * vec_b[1] - vec_a[1] * vec_b[0];
vetk_vec_normalize(vec_a, v2, v1);
vetk_vec_normalize(vec_b, v2, v3);
n[0] += vec_a[1] * vec_b[2] - vec_a[2] * vec_b[1];
n[1] += vec_a[2] * vec_b[0] - vec_a[0] * vec_b[2];
n[2] += vec_a[0] * vec_b[1] - vec_a[1] * vec_b[0];
f = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
normal[j++] = n[0] / f;
normal[j++] = n[1] / f;
normal[j++] = n[2] / f;
}
for(; i < mesh->quad_length + mesh->tri_length; i += 3)
{
v0 = &vertex[mesh->ref[i] * 3];
v1 = &vertex[mesh->ref[i + 1] * 3];
v2 = &vertex[mesh->ref[i + 2] * 3];
vetk_vec_normalize(vec_a, v0, v2);
vetk_vec_normalize(vec_b, v0, v1);
n[0] = vec_a[1] * vec_b[2] - vec_a[2] * vec_b[1];
n[1] = vec_a[2] * vec_b[0] - vec_a[0] * vec_b[2];
n[2] = vec_a[0] * vec_b[1] - vec_a[1] * vec_b[0];
f = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
normal[j++] = n[0] / f;
normal[j++] = n[1] / f;
normal[j++] = n[2] / f;
}
return normal;
}
void vetk_generate_ref(VETKQuadTri *mesh, uint param_count)
{
float *vertex;
uint *ref, i, j, k, used = 0;
vertex = mesh->vertex;
ref = malloc((sizeof *ref) * (mesh->quad_length + mesh->tri_length));
for(i = 0; i < mesh->quad_length + mesh->tri_length; i++)
{
for(j = 0; j < used; j++)
{
/* for(k = 0; k < 6 && vertex[j * param_count + k] > vertex[i * param_count + k] - 0.00001 && vertex[j * param_count + k] < vertex[i * param_count + k] + 0.00001; k++);
if(k == 6)
{
ref[i] = j;
break;
}*/
for(k = 0; k < param_count && vertex[j * param_count + k] > vertex[i * param_count + k] - 0.00001 && vertex[j * param_count + k] < vertex[i * param_count + k] + 0.00001; k++);
if(k == param_count)
{
ref[i] = j;
break;
}
}
if(j == used)
{
for(k = 0; k < param_count; k++)
vertex[used * param_count + k] = vertex[i * param_count + k];
ref[i] = used;
used++;
}
}
mesh->ref = ref;
mesh->vertex_length = used;
}
void vetk_triangulate_vertex(VETKQuadTri *mesh, uint param_count)
{
float *vertex;
uint i, j, k, used = 0;
vertex = mesh->vertex;
mesh->vertex = malloc((sizeof *mesh->vertex) * ((mesh->quad_length / 4 * 6) + mesh->tri_length) * param_count);
for(i = 0; i < mesh->quad_length; i += 4)
{
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 0) * param_count + k];
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 1) * param_count + k];
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 2) * param_count + k];
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 0) * param_count + k];
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 2) * param_count + k];
for(k = 0; k < param_count; k++)
mesh->vertex[used++] = vertex[(i + 3) * param_count + k];
}
for(i = mesh->quad_length * param_count; i < (mesh->quad_length + mesh->tri_length) * param_count; i++)
mesh->vertex[used++] = vertex[i];
mesh->tri_length = ((mesh->quad_length / 4 * 6) + mesh->tri_length);
mesh->quad_length = 0;
free(vertex);
}
void vetk_triangulate_ref(VETKQuadTri *mesh)
{
uint *ref, i, j, k, used = 0;
ref = mesh->ref;
mesh->ref = malloc((sizeof *ref) * ((mesh->quad_length / 4 * 6) + mesh->tri_length));
for(i = 0; i < mesh->quad_length; i += 4)
{
mesh->ref[used++] = ref[i + 0];
mesh->ref[used++] = ref[i + 1];
mesh->ref[used++] = ref[i + 2];
mesh->ref[used++] = ref[i + 0];
mesh->ref[used++] = ref[i + 2];
mesh->ref[used++] = ref[i + 3];
}
for(i = mesh->quad_length; i < (mesh->quad_length + mesh->tri_length); i++)
mesh->ref[used++] = ref[i];
mesh->tri_length = ((mesh->quad_length / 4 * 6) + mesh->tri_length);
mesh->quad_length = 0;
free(ref);
}
uint vetk_triangulate_neighbor_find(VETKQuadTri *mesh, uint edge)
{
if(edge == -1)
return -1;
if(edge > mesh->quad_length)
return (mesh->quad_length * 6 / 4) + (edge - mesh->quad_length);
else
return ((edge / 4) * 6) + ((edge % 4) / 2) * 2+ edge % 4;
}
void vetk_triangulate_neighbor(VETKQuadTri *mesh)
{
uint *n, i, j, k, used = 0;
n = mesh->neighbor;
mesh->neighbor = malloc((sizeof *mesh->neighbor) * ((mesh->quad_length / 4 * 6) + mesh->tri_length));
for(i = 0; i < mesh->quad_length; i += 4)
{
mesh->neighbor[used++] = vetk_triangulate_neighbor_find(mesh, n[i + 0]);
mesh->neighbor[used++] = vetk_triangulate_neighbor_find(mesh, n[i + 1]);
mesh->neighbor[used] = used + 1;
used++;
mesh->neighbor[used] = used - 1;
used++;
mesh->neighbor[used++] = vetk_triangulate_neighbor_find(mesh, n[i + 2]);
mesh->neighbor[used++] = vetk_triangulate_neighbor_find(mesh, n[i + 3]);
}
for(i = mesh->quad_length; i < (mesh->quad_length + mesh->tri_length); i++)
mesh->neighbor[used++] = vetk_triangulate_neighbor_find(mesh, n[i]);
free(n);
}
VETKQuadTri *vetk_create_mesh(ENode *node, char **vertex_params, uint param_count, boolean reference, boolean quads)
{
VETKQuadTri *mesh;
uint i, *crease;
float *data, *poly_normal, *corner_normal;
mesh = malloc(sizeof *mesh);
crease = vetk_poly_clean(node, mesh, vertex_params, param_count);
if(crease == NULL)
{
free(mesh);
return NULL;
}
vetk_compute_neighbor(node, mesh);
poly_normal = vetk_poly_normal(node, mesh);
//(mesh->quad_length / 4 + mesh->tri_length / 3) * 3);
corner_normal = malloc((sizeof *corner_normal) * (mesh->quad_length + mesh->tri_length) * 3);
for(i = 0; i < mesh->quad_length + mesh->tri_length; i++)
vetk_corner_normal(mesh, corner_normal, poly_normal, i, crease);
free(poly_normal);
mesh->vertex = vetk_get_vertex_param(node, mesh, vertex_params, param_count, corner_normal);
free(corner_normal);
if(!quads)
vetk_triangulate_neighbor(mesh);
if(reference)
{
vetk_generate_ref(mesh, param_count);
if(!quads)
vetk_triangulate_ref(mesh);
}
else
{
if(!quads)
vetk_triangulate_vertex(mesh, param_count);
if(mesh->ref != NULL)
{
free(mesh->ref);
mesh->ref = NULL;
}
mesh->vertex_length = mesh->quad_length + mesh->tri_length;
}
free(crease);
return mesh;
}
void vetk_destroy_mesh(VETKQuadTri *mesh)
{
if(mesh->neighbor != NULL)
free(mesh->neighbor);
if(mesh->vertex != NULL)
free(mesh->vertex);
if(mesh->ref != NULL)
free(mesh->ref);
free(mesh);
}