setup examples and clean codebase
This commit is contained in:
48
include/klein/klein.h
Normal file
48
include/klein/klein.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifdef KLEIN_H
|
||||
#error file included twice
|
||||
#endif
|
||||
#define KLEIN_H
|
||||
|
||||
#ifdef KLEIN_IMPLEMENT
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
struct klein
|
||||
{
|
||||
unsigned long vertex_size;
|
||||
float *vertex, *normals;
|
||||
unsigned char dim;
|
||||
};
|
||||
|
||||
/*
|
||||
The klein format must have:
|
||||
5 bytes with klein.
|
||||
1 byte empty for expantions
|
||||
1 byte with the dimention of the surface
|
||||
|
||||
*/
|
||||
|
||||
static inline
|
||||
int klein_export_file(struct klein klein, const char * filename);
|
||||
|
||||
|
||||
#ifdef KLEIN_IMPLEMENT
|
||||
static inline
|
||||
int klein_export_file(struct klein klein, const char * filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "wb");
|
||||
if (!file)
|
||||
return 1;
|
||||
|
||||
fwrite("KLEIN", 1, 5, file);
|
||||
fwrite("\0", 1, 1, file);
|
||||
fwrite(&klein.dim, 1, 1, file);
|
||||
fwrite(&klein.vertex_size, 8, 1, file);
|
||||
fwrite(klein.vertex, 16, klein.vertex_size * klein.dim, file);
|
||||
fwrite(klein.normals, 16, klein.vertex_size * klein.dim, file);
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
118
include/klein/norm.h
Normal file
118
include/klein/norm.h
Normal file
@@ -0,0 +1,118 @@
|
||||
static inline
|
||||
void __calculate_normal( float *p1, float *p2, float *p3, float *normal, unsigned char n)
|
||||
{ unsigned char i;
|
||||
float alpha;
|
||||
float *v1, *v2, *v3;
|
||||
float *u1, *u2, *u3;
|
||||
|
||||
v1 = malloc(n * sizeof(float));
|
||||
v2 = malloc(n * sizeof(float));
|
||||
v3 = malloc(n * sizeof(float));
|
||||
u1 = malloc(n * sizeof(float));
|
||||
u2 = malloc(n * sizeof(float));
|
||||
u3 = malloc(n * sizeof(float));
|
||||
|
||||
/*
|
||||
Calculate a normal vector of a plain using Gram-Schmidt process
|
||||
*/
|
||||
{
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
v1[i] = p2[i] - p1[i];
|
||||
v2[i] = p3[i] - p1[i];
|
||||
v3[i] = p1[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
u1[i] = v1[i];
|
||||
}
|
||||
|
||||
{
|
||||
float proj[n];
|
||||
float dot_v2_u1 = 0.0f, dot_u1_u1 = 0.0f;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
dot_v2_u1 += v2[i] * u1[i];
|
||||
dot_u1_u1 += u1[i] * u1[i];
|
||||
}
|
||||
alpha = dot_v2_u1 / dot_u1_u1;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
proj[i] = u1[i] * alpha;
|
||||
u2[i] = v2[i] - proj[i];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float proj1[n], proj2[n];
|
||||
float dot_v3_u1 = 0.0f, dot_u1_u1 = 0.0f;
|
||||
float dot_v3_u2 = 0.0f, dot_u2_u2 = 0.0f;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
dot_v3_u1 += v3[i] * u1[i];
|
||||
dot_u1_u1 += u1[i] * u1[i];
|
||||
}
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
proj1[i] = u1[i] * (dot_v3_u1 / dot_u1_u1);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
dot_v3_u2 += v3[i] * u2[i];
|
||||
dot_u2_u2 += u2[i] * u2[i];
|
||||
}
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
proj2[i] = u2[i] * (dot_v3_u2 / dot_u2_u2);
|
||||
u3[i] = v3[i] - proj1[i] - proj2[i];
|
||||
}
|
||||
}
|
||||
|
||||
float magnitude = 0.0f;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
magnitude += u3[i] * u3[i];
|
||||
}
|
||||
magnitude = sqrtf(magnitude);
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
normal[i] = u3[i] / magnitude;
|
||||
}
|
||||
|
||||
free(v1);
|
||||
free(v2);
|
||||
free(v3);
|
||||
free(u1);
|
||||
free(u2);
|
||||
free(u3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void klein_normalize(struct klein * klein)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned char j;
|
||||
float *norm_vec;
|
||||
|
||||
klein->normals = malloc((klein->dim * klein->vertex_size) * sizeof(float));
|
||||
norm_vec = malloc(klein->dim * sizeof(float));
|
||||
|
||||
for (i = 0; i < klein->vertex_size; i += 3 * klein->dim)
|
||||
{
|
||||
__calculate_normal(klein->vertex + i, klein->vertex + i + klein->dim, klein->vertex + i + 2 * klein->dim, norm_vec, klein->dim);
|
||||
for (j = 0; j < klein->dim; ++j )
|
||||
{
|
||||
(klein->normals + i)[j]=norm_vec[j];
|
||||
(klein->normals + i + klein->dim)[j]=norm_vec[j];
|
||||
(klein->normals + i + 2*klein->dim)[j]=norm_vec[j];
|
||||
}
|
||||
}
|
||||
|
||||
free(norm_vec);
|
||||
}
|
||||
134
include/klein/parm.h
Normal file
134
include/klein/parm.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#ifndef KLEIN_H
|
||||
#warning Please include klein/klein.h before klein/parm.h
|
||||
#endif
|
||||
|
||||
#ifdef KLEIN_PARM_H
|
||||
#error file included twice
|
||||
#endif
|
||||
#define KLEIN_PARM_H
|
||||
|
||||
|
||||
typedef void (*function_t)(float *, int *, unsigned char *);
|
||||
|
||||
struct parm
|
||||
{
|
||||
unsigned char *grid;
|
||||
unsigned char m, n;
|
||||
function_t f;
|
||||
};
|
||||
|
||||
|
||||
void klein_parametrize( struct klein * klein, struct parm parm );
|
||||
|
||||
#ifdef KLEIN_IMPLEMENT
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
static inline int __factorial(int n)
|
||||
{
|
||||
if (n == 1)
|
||||
return 1;
|
||||
|
||||
return n * __factorial(n - 1);
|
||||
}
|
||||
|
||||
static inline int __face(int n)
|
||||
{
|
||||
if (n == 2)
|
||||
return 1;
|
||||
|
||||
return (1 << (n - 3)) * __factorial(n) / __factorial(n - 2);
|
||||
}
|
||||
|
||||
void klein_parametrize( struct klein * klein, struct parm parm)
|
||||
{
|
||||
unsigned int i, j, k, o, p, n;
|
||||
unsigned long size, q = 0;
|
||||
int *face;
|
||||
|
||||
#ifdef TEST
|
||||
assert(__face(2) == 1);
|
||||
assert(__face(3) == 6);
|
||||
assert(__face(4) == 24);
|
||||
#endif
|
||||
|
||||
klein->dim = parm.n;
|
||||
klein->vertex_size = 0;
|
||||
{
|
||||
unsigned char test = 0;
|
||||
for (o = 0; o < parm.m; o++)
|
||||
{
|
||||
for (p = 0; p < o; p++)
|
||||
{
|
||||
test += 1;
|
||||
klein->vertex_size += parm.grid[p] * parm.grid[o] * 6 * __face(parm.m);
|
||||
}
|
||||
}
|
||||
klein->vertex_size /= test;
|
||||
}
|
||||
|
||||
size = (klein->dim) * (klein->vertex_size);
|
||||
klein->vertex = malloc(size * sizeof(float));
|
||||
|
||||
face = malloc(parm.m * sizeof(int));
|
||||
|
||||
for (o = 0; o < parm.m; o++)
|
||||
{
|
||||
for (p = 0; p < o; p++)
|
||||
{
|
||||
for (k = 0; k < (1 << (parm.m - 2)); k++)
|
||||
{
|
||||
unsigned char skip = 0;
|
||||
for (n = 0; n < parm.m; n++)
|
||||
{
|
||||
if (n == o || n == p)
|
||||
skip++;
|
||||
|
||||
face[n] = (k & (1 << (n - skip))) ? parm.grid[n] : 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < parm.grid[p]; i++)
|
||||
{
|
||||
for (j = 0; j < parm.grid[o]; j++)
|
||||
{
|
||||
face[p] = i;
|
||||
face[o] = j;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
|
||||
face[p] = i + 1;
|
||||
face[o] = j;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
|
||||
face[p] = i + 1;
|
||||
face[o] = j + 1;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
|
||||
face[p] = i;
|
||||
face[o] = j;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
|
||||
face[p] = i;
|
||||
face[o] = j + 1;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
|
||||
face[p] = i + 1;
|
||||
face[o] = j + 1;
|
||||
parm.f(&klein->vertex[q], face, parm.grid);
|
||||
q += parm.n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
assert(q == size);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user