setup examples and clean codebase

This commit is contained in:
PedroEdiaz
2024-12-03 22:18:48 -06:00
parent f8eb20c0cf
commit f514fc7ffe
9 changed files with 516 additions and 438 deletions

48
include/klein/klein.h Normal file
View 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
View 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
View 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