A tiny software raymarcher that attempts to render "n-dimension" manofold insertions as an image appearing to be a non-euclidean 3-dimensional space. Written for the uqcs hackathon 2020. This repo is a mirror of: https://github.com/ailrst/blackpink
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

374 lines
9.0 KiB

#include "vect.h"
#include <math.h>
#include <float.h>
/**
* Creates a new vec* struct with the given number of dimenions.
* All elements are set to 0.
*/
struct vec*
new_vec(int num_dimensions)
{
struct vec* new_vector = calloc(1,sizeof(struct vec));
new_vector->dimension = num_dimensions;
new_vector->elements = calloc(num_dimensions, sizeof(double));
return new_vector;
}
struct vec* do_on_vec_ip(struct vec * v, double (*func)(double)) {
for (int i = 0; i < v->dimension; i++) {
v->elements[i] = func(v->elements[i]);
}
return v;
}
struct vec*
new_vec_of(int num_dimensions, double value) {
struct vec* new_vector = new_vec(num_dimensions);
for (int i = 0; i < num_dimensions; i++) {
new_vector->elements[i] = value;
}
return new_vector;
}
/**
* Frees all memory related to the given vec.
*/
void
free_vec(struct vec* a)
{
free(a->elements);
free(a);
}
/**
* Copies the given vector into the newly malloc'd vector.
*/
struct vec*
copy_vec(struct vec* to_copy)
{
struct vec* new_vector = new_vec(to_copy->dimension);
for (int i = 0; i < to_copy->dimension; i++) {
new_vector->elements[i] = to_copy->elements[i];
}
return new_vector;
}
/**
* Takes 2 doubles and creates an vec of 2 dimensions.
*/
struct vec*
new_vec2(double x, double y)
{
struct vec* new_vector = new_vec(2);
new_vector->elements[0] = x;
new_vector->elements[1] = y;
return new_vector;
}
/**
* Takes 3 doubles and creates an vec of 3 dimensions.
*/
struct vec*
new_vec3(double x, double y, double z)
{
struct vec* new_vector = new_vec(3);
new_vector->elements[0] = x;
new_vector->elements[1] = y;
new_vector->elements[2] = z;
return new_vector;
}
/**
* Takes 4 doubles and creates an vec of 4 dimensions.
*/
struct vec*
new_vec4(double w, double x, double y, double z)
{
struct vec* new_vector = new_vec(4);
new_vector->elements[0] = w;
new_vector->elements[1] = x;
new_vector->elements[2] = y;
new_vector->elements[3] = z;
return new_vector;
}
/**
* Adds together two vecs and returns a reference to the summed vec.
*/
struct vec*
add_vec(struct vec* a, struct vec* b)
{
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension ? a->dimension : b->dimension;
// Perform addition up to where the dimensions of both vectors are equal.
struct vec* result = new_vec(a->dimension);
for (int i = 0; i < smallest_dimension; i++) {
result->elements[i] = a->elements[i] + b->elements[i];
}
// Assume the smaller array is all 0s if the dimensions aren't equal
for (int i = smallest_dimension; i < largest_dimension; i++) {
if (largest_dimension == a->dimension) {
result->elements[i] = a->elements[i];
} else if (largest_dimension == b->dimension) {
result->elements[i] = b->elements[i];
}
}
return result;
}
/**
* Add vec a to vec b and return the pointer to vec a.
*/
struct vec*
add_vec_ip(struct vec* a, struct vec* b)
{
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension? a->dimension : b->dimension;
for (int i = 0; i < smallest_dimension; i++) {
a->elements[i] = a->elements[i] + b->elements[i];
}
// Assume the smaller array is all 0s if the dimensions aren't equal
for (int i = smallest_dimension; i < largest_dimension; i++) {
if (largest_dimension == a->dimension) {
a->elements[i] = a->elements[i];
} else if (largest_dimension == b->dimension) {
a->elements[i] = b->elements[i];
}
}
return a;
}
/**
* Add vec a to vec b * scaleFactor and store in vec a. Returns a pointer to vec a.
*/
struct vec*
add_scaled_vec_ip(struct vec* a, struct vec* b, double scaleFactor) {
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension? a->dimension : b->dimension;
for (int i = 0; i < smallest_dimension; i++) {
a->elements[i] = a->elements[i] + b->elements[i] * scaleFactor;
}
// Assume the smaller array is all 0s if the dimensions aren't equal
for (int i = smallest_dimension; i < largest_dimension; i++) {
if (largest_dimension == a->dimension) {
a->elements[i] = a->elements[i];
} else if (largest_dimension == b->dimension) {
a->elements[i] = b->elements[i] * scaleFactor;
}
}
return a;
}
/**
* Subtracts vec b from vec a and returns a reference to the difference vec.
*/
struct vec*
subtract_vec(struct vec* a, struct vec* b)
{
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension? a->dimension : b->dimension;
// Perform subtraction up to where the dimensions of both vectors are equal.
struct vec* result = new_vec(a->dimension);
for (int i = 0; i < smallest_dimension; i++) {
result->elements[i] = a->elements[i] - b->elements[i];
}
// Assume the smaller array is all 0s if the dimensions aren't equal
for (int i = smallest_dimension; i < largest_dimension; i++) {
if (largest_dimension == a->dimension) {
result->elements[i] = a->elements[i];
} else if (largest_dimension == b->dimension) {
result->elements[i] = - b->elements[i];
}
}
return result;
}
/**
* Subtracts vec b from vec a and stores the result in vec a, returning a
* pointer to it as well.
*/
struct vec*
subtract_vec_ip(struct vec* a, struct vec* b)
{
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension? a->dimension : b->dimension;
// Perform subtraction up to where the dimensions of both vectors are equal.
for (int i = 0; i < smallest_dimension; i++) {
a->elements[i] = a->elements[i] - b->elements[i];
}
// Assume the smaller array is all 0s if the dimensions aren't equal
for (int i = smallest_dimension; i < largest_dimension; i++) {
if (largest_dimension == a->dimension) {
break; // the elements of a don't need to be changed
} else if (largest_dimension == b->dimension) {
a->elements[i] = - b->elements[i];
}
}
return a;
}
/**
* Calculates the magnitude of vec a.
*/
double
magnitude_vec(struct vec* a)
{
double sum_of_squares = 0;
for (int i = 0; i < a->dimension; i++) {
sum_of_squares +=a->elements[i] * a->elements[i];
}
return sqrt(sum_of_squares);
}
/**
* Normalise the given vec by dividing all components by the magnitude.
*/
struct vec*
normalise_vec(struct vec* a)
{
struct vec* result = new_vec(a->dimension);
double magnitude = magnitude_vec(a);
for (int i = 0; i < a-> dimension; i++) {
result->elements[i] = a->elements[i] / magnitude;
}
return result;
}
/**
* Normalise the given vec and store in vec a.
*/
struct vec*
normalise_vec_ip(struct vec* a)
{
double magnitude = magnitude_vec(a);
for (int i = 0; i < a-> dimension; i++) {
a->elements[i] = a->elements[i] / magnitude;
}
return a;
}
/**
* Calculate the dot product of vec a and vec b.
*/
double
dot_product_vec(struct vec* a, struct vec* b)
{
double result = 0;
for (int i = 0; i < a->dimension; i++) {
result += a->elements[i] * b->elements[i];
}
return result;
}
/**
* Multiply vec a by a scalarFactor and return a new vec with the result.
*/
struct vec*
scalar_multiply_vec(struct vec* a, double scalarFactor)
{
struct vec* result = new_vec(a->dimension);
for (int i = 0; i < a->dimension; i++) {
result->elements[i] = a->elements[i] * scalarFactor;
}
return result;
}
/**
* Multiply vec a by a scalarFactor and return vec a with the result.
*/
struct vec*
scalar_multiply_vec_ip(struct vec* a, double scalarFactor)
{
for (int i = 0; i < a->dimension; i++) {
a->elements[i] *= scalarFactor;
}
return a;
}
/**
* Calculate the distance between vec a and vec b by summing the square of
* the differences of each component.
*/
double
distance_vec(struct vec* a, struct vec* b)
{
double sum_of_differences = 0;
for (int i = 0; i < a->dimension; i++) {
sum_of_differences = pow(a->elements[i] - b->elements[i], 2);
}
return sqrt(sum_of_differences);
}
double
vec_max(const struct vec *v)
{
double max = -DBL_MAX;
for (int i = 0; i < v->dimension; i++) {
if (i > max)
max = v->elements[i];
}
return max;
}
double
vec_min(const struct vec *v)
{
double min = DBL_MAX;
for (int i = 0; i < v->dimension; i++) {
if (i < min)
min = v->elements[i];
}
return min;
}
/**
* Takes an array of n vectors and returns a vector perpendicular to all of them.
*/
struct vec*
perpendicular_vec(struct vec** vectors)
{
;
}