ANSI C library for NURBS, B-Splines, and Bézier curves with interfaces for C++, C#, D, Go, Java, Lua, Octave, PHP, Python, R, and Ruby.

Overview

TinySpline

CI Language grade: C/C++

TinySpline is a small, yet powerful library for interpolating, transforming, and querying arbitrary NURBS, B-Splines, and Bézier curves. The library is implemented in ANSI C (C89) and provides a wrapper for C++ along with auto-generated bindings for C#, D, Go, Java, Lua, Octave, PHP, Python, R, and Ruby.

License

MIT License - see the LICENSE file in the source distribution.

Installation

Pre-built Binaries

Releases can be downloaded from the releases page.

In addition, the following package manager are supported:

Luarocks (Lua; currently only Linux and macOS):

luarocks install --server=https://msteinbeck.github.io/tinyspline/luarocks tinyspline

Maven (Java):

<dependency>
   <groupId>org.tinyspline</groupId>
   <artifactId>tinyspline</artifactId>
   <version>0.3.0-2</version>
</dependency>

PyPI (Python):

python -m pip install tinyspline

Compiling From Source

See BUILD.md.

Getting Started

The following listing uses the ANSI C interface:

#include "tinyspline.h"
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
	tsStatus status;   /**< Used for error handling. */

	tsBSpline spline;  /**< The spline to setup. */
	tsReal *ctrlp;     /**< Pointer to the control points of `spline`. */

	tsBSpline beziers; /**< `spline` as a sequence of bezier curves. */

	tsDeBoorNet net;   /**< Used to evaluate `spline` and `beziers`. */
	tsReal *result;    /**< Pointer to the result of `net`. */

/* ------------------------------------------------------------------------- */
/* TinySpline includes a powerful, system-independent, and thread-safe error
 * handling system. Embed your code into a TS_TRY/TS_END_TRY block and use
 * TS_CALL when calling a TinySpline function. Likewise, you can use any of
 * the TS_THROW macros to raise an error if an external function (e.g.,
 * malloc) failed.
 *
 * Errors can be handled with TS_CATCH. TS_FINALLY contains code that is
 * executed in any case, therefore being perfectly suitable for cleaning up
 * resources. That said, error handling is entirely optional. You may omit
 * TS_TRY/TS_END_TRY, TS_CALL, and TS_THROW and pass NULL instead of a pointer
 * to a tsStatus object. */

	spline = ts_bspline_init();
	beziers = ts_bspline_init();
	net = ts_deboornet_init();
	ctrlp = result = NULL;
	TS_TRY(try, status.code, &status)
		/* Create a spline... */
		TS_CALL(try, status.code, ts_bspline_new(
			7, /* ... consisting of 7 control points... */
			2, /* ... in 2D... */
			3, /* ... of degree 3... */
			TS_CLAMPED, /* ... using a clamped knot vector. */
			&spline, &status))

		/* Setup control points of `spline`. */
		TS_CALL(try, status.code, ts_bspline_control_points(
			&spline, &ctrlp, &status))
		ctrlp[0]  = -1.75f; /* x0 */
		ctrlp[1]  = -1.0f;  /* y0 */
		ctrlp[2]  = -1.5f;  /* x1 */
		ctrlp[3]  = -0.5f;  /* y1 */
		ctrlp[4]  = -1.5f;  /* x2 */
		ctrlp[5]  =  0.0f;  /* y2 */
		ctrlp[6]  = -1.25f; /* x3 */
		ctrlp[7]  =  0.5f;  /* y3 */
		ctrlp[8]  = -0.75f; /* x4 */
		ctrlp[9]  =  0.75f; /* y4 */
		ctrlp[10] =  0.0f;  /* x5 */
		ctrlp[11] =  0.5f;  /* y5 */
		ctrlp[12] =  0.5f;  /* x6 */
		ctrlp[13] =  0.0f;  /* y6 */
		TS_CALL(try, status.code, ts_bspline_set_control_points(
			&spline, ctrlp, &status))

		/* Evaluate `spline` at u = 0.4. */
		TS_CALL(try, status.code, ts_bspline_eval(
			&spline, 0.4f, &net, &status))
		TS_CALL(try, status.code, ts_deboornet_result(
			&net, &result, &status))
		printf("x = %f, y = %f\n", result[0], result[1]);

		/* Derive `spline` ... */
		TS_CALL(try, status.code, ts_bspline_derive(
			&spline, 1, TS_CONTROL_POINT_EPSILON,
			&beziers, &status))
		/* ... and subdivide it into a sequence of Bezier curves. */
		TS_CALL(try, status.code, ts_bspline_to_beziers(
			&beziers, &beziers, &status))

		ts_deboornet_free(&net);
		free(result);
		/* Evaluate `beziers` at u = 0.3. */
		TS_CALL(try, status.code, ts_bspline_eval(
			&beziers, 0.3f, &net, &status))
		TS_CALL(try, status.code, ts_deboornet_result(
			&net, &result, &status))
		printf("x = %f, y = %f\n", result[0], result[1]);
	TS_CATCH(status.code)
		puts(status.message);
	TS_FINALLY
		ts_bspline_free(&spline);
		ts_bspline_free(&beziers);
		ts_deboornet_free(&net);
		if (ctrlp)
			free(ctrlp);
		if (result)
			free(result);
	TS_END_TRY

	return status.code? 1 : 0;
}

The same example using the C++ interface:

#include <iostream>
#include "tinysplinecpp.h"

int main(int argc, char **argv)
{
	// Create a cubic spline with 7 control points in 2D using
	// a clamped knot vector. This call is equivalent to:
	// tinyspline::BSpline spline(7, 2, 3, TS_CLAMPED);
	tinyspline::BSpline spline(7);

	// Setup control points.
	std::vector<tinyspline::real> ctrlp = spline.controlPoints();
	ctrlp[0]  = -1.75; // x0
	ctrlp[1]  = -1.0;  // y0
	ctrlp[2]  = -1.5;  // x1
	ctrlp[3]  = -0.5;  // y1
	ctrlp[4]  = -1.5;  // x2
	ctrlp[5]  =  0.0;  // y2
	ctrlp[6]  = -1.25; // x3
	ctrlp[7]  =  0.5;  // y3
	ctrlp[8]  = -0.75; // x4
	ctrlp[9]  =  0.75; // y4
	ctrlp[10] =  0.0;  // x5
	ctrlp[11] =  0.5;  // y5
	ctrlp[12] =  0.5;  // x6
	ctrlp[13] =  0.0;  // y6
	spline.setControlPoints(ctrlp);

	// Evaluate `spline` at u = 0.4 using 'eval'.
	std::vector<tinyspline::real> result = spline.eval(0.4).result();
	std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;

	// Derive `spline` and subdivide it into a sequence of Bezier curves.
	tinyspline::BSpline beziers = spline.derive().toBeziers();

	// Evaluate `beziers` at u = 0.3 using '()' instead of 'eval'.
	result = beziers(0.3).result();
	std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;

	return 0;
}

Theoretical Backgrounds

[1] is a very good starting point for B-Splines.

[2] explains De Boor's Algorithm and gives some pseudo code.

[3] provides a good overview of NURBS with some mathematical background.

[4] is useful if you want to use NURBS in TinySpline.

Comments
  • CMake updates: add options + use BUILD_SHARED_LIBS + export targets + win32 dll

    CMake updates: add options + use BUILD_SHARED_LIBS + export targets + win32 dll

    Hello, we are currently reviewing a request for adding tinyspline in conan-center-index at https://github.com/conan-io/conan-center-index/pull/3149 conan-center-index is a central repo for recipes for conan, which is a c/c++ package manager. Long story short, this will allow c/c++ developers to use tinyspline with a simple conan install tinyspline/x.y

    While reviewing, we needed to apply some changes to the cmake build script. In order for you to benefit from these, I have applied them to the current master. I have separated the changes as much as possible in patches.

    After the patches, the following is possible:

    • optionally build examples/tests/docs This is useful for us, packages, as we won't add the examples/tests to the packages
    • optionally enable -Werroror /WX. This makes the build more robust. Granted, warnings should be avoided as much as possible, but a new compiler version will introduce new warnings which will break future builds. This change allows you, the developer, to fail on errors, but will allow users to ignore these warnings.
    • Don't build shared and static libraries at the same time. CMake has a BUILD_SHARED_LIBS option that will change the behavior of add_library. It's uncommon for a dependency of a library to require a shared and a static library at the same time.
    • Avoid a OpenGL warning. See https://cmake.org/cmake/help/latest/module/FindOpenGL.html#linux-specific.
    • Link the system libraries to the tinyspline target immediately. By making use of targets, the TINYSPLINE_C_STATIC_LIBRARIES cmake variable should not be added to the library list of dependencies/examples.
    • The ctest change allows running make test in the root directory
    • By tagging the symbols in the headers with __declspec(dllexport) on a shared build on Windows, it is possible to create a tinyspline dll + import library.
    • The python bump on travis is required, because yesterday cpython 3.9 was released.
    opened by madebr 37
  • Precision

    Precision

    Hi Marcel

    Another question: I have source data which needs double precision. I have seen that there is a definition for max. relative and absolute errors. If I would change everything to double and change the precision accordingly, do I get some problems with that?

    Kind regards, Renato

    opened by resema 30
  • Conversion from B-spline to piecewise polynomial representation

    Conversion from B-spline to piecewise polynomial representation

    Hello Marcel,

    I'm using TinySpline in my project and need to convert a B-Spline result to a piecewise polynomial representation, as the servo drive controller I'm using the generated curves for only supports polynomial formats. That is, given a B-Spline function f with knot vector and control points, I want to retreive the piecewise polynomials of im(f) in coefficient form.

    What I found so far is that I could try to implement the bsplpp Fortran algorithm introduced by Carl de Boor: https://github.com/ratnania/spipp/blob/master/fortran/pppack/bsplpp.F90

    Also, scipy seems to offer the method "fromspline" which I could try to recreate using TinySpline: https://github.com/scipy/scipy/blob/master/scipy/interpolate/interpolate.py#L938

    Which way would you recomend using TinySpline, or is there a convenient method using your library already, which I'm missing?

    Thanks in Advance, Hannes

    opened by hwaclawek 21
  • Spline to XYZ coordinates

    Spline to XYZ coordinates

    Hi @msteinbeck,

    This is not an issue, just a quick question regarding the conversion of a BSpline using InterpolateCubicNatural to XYZ coordinates.

    Looking at the examples, would I use the sample( ) function to get XYZ coordinates to plot the necessary lines to represent the spline?

    opened by onslauth 19
  • Install and find SyntaxError: invalid syntax

    Install and find SyntaxError: invalid syntax

    Hi, I follow the install instruction:

    export PYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so
    export PYTHON_INCLUDE_DIR=/usr/include/python2.7
    python setup.py install
    

    and get SyntaxError: invalid syntax

    generating python binding
    [ 20%] Swig source
    Scanning dependencies of target _tinysplinepython
    [ 40%] Building CXX object CMakeFiles/_tinysplinepython.dir/python/tinysplinepythonPYTHON_wrap.o
    [ 60%] Building C object CMakeFiles/_tinysplinepython.dir/tinyspline.o
    [ 80%] Building CXX object CMakeFiles/_tinysplinepython.dir/tinysplinecpp.o
    [100%] Linking CXX shared module _tinysplinepython.so
    [100%] Built target _tinysplinepython
    creating file: __init__.py
    package init file './__init__.py' not found (or not a regular file)
    package init file './__init__.py' not found (or not a regular file)
    removing cmake build directory
    running install_lib
    copying build/lib.linux-x86_64-2.7/tinyspline/tinyspline.py -> /usr/local/lib/python2.7/dist-packages/tinyspline
    copying build/lib.linux-x86_64-2.7/tinyspline/_tinysplinepython.so -> /usr/local/lib/python2.7/dist-packages/tinyspline
    copying build/lib.linux-x86_64-2.7/tinyspline/__init__.py -> /usr/local/lib/python2.7/dist-packages/tinyspline
    byte-compiling /usr/local/lib/python2.7/dist-packages/tinyspline/tinyspline.py to tinyspline.pyc
      File "/usr/local/lib/python2.7/dist-packages/tinyspline/tinyspline.py", line 111
        def ts_deboornet_default(deBoorNet: 'tsDeBoorNet *') -> "void":
                                          ^
    SyntaxError: invalid syntax
    
    

    Could you please help? Thank you.

    opened by cbjcbj 18
  • Has anyone gotten tinyspline to work on a Mac using Python in an Anaconda environment?

    Has anyone gotten tinyspline to work on a Mac using Python in an Anaconda environment?

    I'm using Catalina (10.15.7) on an old Macbook Pro.

    I got tinyspline to work in a non-Anaconda environment, using the system Python3 (/usr/local/bin/python3), otool, and install_name_tool.

    I used the install from source method. Tinyspline was installed at /usr/local/lib/python3.9/site-packages/tinyspline.

    I used otool -l _tinyspline.so to identify the dylib to change. I found the name of the new dylib by searching for libpython3.9.dylib .

    Then I ran

    install_name_tool -change "name-of-original-python-dylib" "/usr/local/Cellar/[email protected]/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/libpython3.9.dylib" _tinyspline.so

    (Syntax is install_name_tool -change "old-dylib" "new-dylib" _tinyspline.so)

    I verified that the change was successful using otool -l _tinyspline.so again. I entered the sample program and it worked.

    All good. But this process didn't work in either an Anaconda Python 3.8 or 3.9 environment. I tried using pip(3) and the manual procedure above. The Python statement ' from tinyspline import *' segfaulted both times.

    I can accomplish what I want to do in the system Python environment, but it's cumbersome, since I normally use an Anaconda environment.

    Any suggestions?

    Thanks for your help!

    opened by m-bob 17
  • Unspecified value for tsError when calling ts_bspline_evaluate multiple times

    Unspecified value for tsError when calling ts_bspline_evaluate multiple times

    Hello,

    First, excellent library, very useful. Thank you!

    I've been implementing a binary search to allow finding an exact match to a cubic spline fit. The setup is like this:

    `volatile tsError splinerr=TS_SUCCESS; /* Stores our evaluation results. */ tsDeBoorNet net;

    	tsBSpline spline_interp;
    	tsReal points[12];
    
    	  //Stock - likely move this to flash
    	  points[0]  = 2.0f; /* x0 */
    	  points[1]  = 30.68f;  /* y0 */
    	  points[2]  = 716.0f;  /* x1 */
    	  points[3]  = 20.8946f;  /* y1 */
    	  points[4]  = 1588.0f;  /* x2 */
    	  points[5]  =  13.1714f;  /* y2 */
    	  points[6]  = 2473.0f; /* x3 */
    	  points[7]  =  6.0488f;  /* y3 */
    	  points[8]  = 3282.0f; /* x4 */
    	  points[9]  =  1.9933f; /* y4 */
    	  points[10] =  4059.0f;  /* x5 */
    	  points[11] =  0.9598f;  /* y5 */
    	}
    
    	splinerr = ts_bspline_interpolate_cubic(points, 6, 2, &spline_interp);
    
    	u = (float) (counts) / 4095.0f;  //Normalize for lookup...
    

    /* Must binomial search or simliar to hone in on the actual X value, the spline 'u' is proportional distance along curve. / #define CLOSE_ENOUGH 4.0f //counts that we would consider 'close enough' for (i = 0; i<10; i++) //Only try 10 times though, in case something is strange { splinerr = ts_bspline_evaluate(&spline_interp, u, &net); err = net.result[0] - (float) counts; //net.result[0] is the 'x' axis for a given normalized 'u' input and should match the counts.... if ( (err <= CLOSE_ENOUGH) && (err >= -CLOSE_ENOUGH) ){ break; } //get out u = u - 0.0001err;

    	  //  printf("%u,%f,%f,%f\n", i, u, err, net.result[0]);
    
    	}
    
    	if(u<0.0f) u = 0.0f;
    	if(u>1.0f) u = 1.0f;
    	ts_bspline_evaluate(&spline_interp, u, &net);
    	FOV = net.result[1];
    	ts_deboornet_free(&net);
    /* Cleanup */
    ts_bspline_free(&spline_interp);
    

    `

    Looks sloppy on the search, and will clean that up, but the real problem is that if i run through this routine 16 times, then this line: splinerr = ts_bspline_evaluate(&spline_interp, u, &net);

    returns an error that is not in this list:

    `typedef enum { /* No error. */ TS_SUCCESS = 0,

    /* Unable to allocate memory (using malloc/realloc). */
    TS_MALLOC = -1,
    
    /* The dimension of the control points are 0. */
    TS_DIM_ZERO = -2,
    
    /* Degree of spline (deg) >= number of control points (n_ctrlp). */
    TS_DEG_GE_NCTRLP = -3,
    
    /* Spline is not defined at knot value u. */
    TS_U_UNDEFINED = -4,
    
    /* Multiplicity of a knot (s) > order of spline.  */
    TS_MULTIPLICITY = -5,
    
    /* Decreasing knot vector. */
    TS_KNOTS_DECR = -6,
    
    /* Unexpected number of knots. */
    TS_NUM_KNOTS = -7,
    
    /* Spline is not derivable */
    TS_UNDERIVABLE = -8
    

    } tsError;`

    Instead, my debugger is showing a value of 255 being returned for this tsError.

    I thought it might be a memory issue, but heap/stack changes don't affect it and neither does wrapping 'free' around these variables each of the inner loop cycles and creating them again.

    Do you know what the 255 might represent?

    opened by matterama 17
  • Debug postfix

    Debug postfix

    CMake has a simple mechanism to add a debug postfix: https://cmake.org/cmake/help/v3.0/command/set_target_properties.html

    This is handy to identify debug and release version of a library or application (e.g., for the examples).

    opened by giumas 16
  • Structure the example module

    Structure the example module

    Currently, all examples are placed in example. However, I would like to add more examples for C++, Java, etc. in future. Thus, we should create submodules within example similar to the approach used in the units-tests branch. That is, each language gets its own module in example, for instance, example/c, example/cpp, example/java, and so on.

    Furthermore, @giumas suggested to rename example into examples. I'm fine with both. Are there best practices for this?

    opened by msteinbeck 16
  • Add packages to generate bindings on Linux

    Add packages to generate bindings on Linux

    All of the packages needed to generate the different bindings are now installed by Travis' Linux machines. Please note, as #86 explains, Swig is out of date on APT and PHP cannot be generated and tested by Travis CI just yet.

    opened by queengooborg 15
  • Trouble converting NURB to bezier using tinyspline

    Trouble converting NURB to bezier using tinyspline

    Hello!

    I've been using tinypline to convert NURBS data into beziers and it mostly works. However, I've encountered a situation where BSpline::toBeziers() throws an exception:

    knot (0.000000) < min(domain) (0.000000)

    I'm getting NURBS data from a library that deals with DGN & DXF files, and I'm not sure why this particular geometry is a problem. The only difference seems to be in the knot vector. All of the geometries are two dimensional, 4th order NURBS, but the troublesome knot vector starts with four negative numbers instead of the expected four zeroes. After plugging them into the tinyspline object, I ask for the knots back and they've clearly be normalized over [0, 1]. But calling toBeziers() causes the above exception.

    I can't tell if I'm doing something wrong with tinyspline or if I'm supposed to do something to the data before giving it to tinyspline. I've found that if I zero out the four negative knots, the exception goes away, but that feels sketchy for obvious reasons.

    If it helps, I can post the full raw NURBS data, but I was hoping you might just know from my description what I'm doing wrong.

    Thanks! (Also, thanks for the great library!)

    opened by AndrewAtAvenza 14
  • parson conflicts with json-c library

    parson conflicts with json-c library

    I'm trying to use tinyspline with other libs which depend on json-c library, but I fail to link them because parson & json-c are using the same functions names. Is it possible to make JSON suport optional or rename parson's function or somehow hide them ?

    opened by bog-dan-ro 3
Releases(v0.5.0)
Owner
Marcel Steinbeck
Marcel Steinbeck
HARFANG®3D is an all-in-one 3D visualization library usable in C++, Python, Lua and Go.

HARFANG® 3D engine HARFANG®3D is an all-in-one 3D visualization library usable in C++, Python, Lua and Go. Table of contents About Features Screenshot

HARFANG® 3D 280 Jan 1, 2023
A tiny uefi graphical user interfaces libaray......

TUGUI a tiny uefi graphical user interfaces libaray...... 1.最近动态 1.添加 数学相关基础库 齐次坐标 .... 2.图形学 变换 2D/3D .... 2. 编译运行 2.1 开发环境 编译工具链: g++-mingw-w64-x86-

UnknownBugs 4 Jan 12, 2022
C++ (with python bindings) library for easily reading/writing/manipulating common animation particle formats such as PDB, BGEO, PTC. See the discussion group @ http://groups.google.com/group/partio-discuss

Partio - A library for particle IO and manipulation This is the initial source code release of partio a tool we used for particle reading/writing. It

Walt Disney Animation Studios 412 Dec 29, 2022
Polyscope is a C++/Python viewer and user interface for 3D data such as meshes and point clouds

Polyscope is a C++/Python viewer and user interface for 3D data such as meshes and point clouds. It allows you to register your data and quickly generate informative and beautiful visualizations, either programmatically or via a dynamic GUI.

Nicholas Sharp 1.3k Dec 30, 2022
Python binding for Grasp Pose Generator (pyGPG)

Python binding for Grasp Pose Generator (pyGPG) Grasp Pose Generator is a cpp package that creat grasp candidates for 3D point clouds. This package bi

Hongzhuo Liang 11 Dec 16, 2022
⚡High-performance rendering for python

ZenGL ZenGL is a minimalist Python module providing exactly one way to render scenes with OpenGL. pip install zengl Documentation zengl on Github zen

Szabolcs Dombi 133 Dec 17, 2022
StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR!

StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR! Inspired by libraries like XNA and Processing, StereoKit is meant to be fun to use and easy to develop with, yet still quite capable of creating professional and business ready software.

Nick Klingensmith 730 Jan 4, 2023
Draco is a library for compressing and decompressing 3D geometric meshes and point clouds.

Draco is a library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.

Google 5.4k Dec 30, 2022
A multi core friendly rigid body physics and collision detection library suitable for games and VR applications.

A multi core friendly rigid body physics and collision detection library suitable for games and VR applications.

null 2.5k Jan 4, 2023
DirectX 11 and 12 library that provides a scalable and GCN-optimized solution for deferred shadow filtering

AMD ShadowFX The ShadowFX library provides a scalable and GCN-optimized solution for deferred shadow filtering. Currently the library supports uniform

GPUOpen Effects 163 Dec 9, 2022
The official Open-Asset-Importer-Library Repository. Loads 40+ 3D-file-formats into one unified and clean data structure.

Open Asset Import Library (assimp) A library to import and export various 3d-model-formats including scene-post-processing to generate missing render

Open Asset Import Library 8.6k Jan 4, 2023
A modern cross-platform low-level graphics library and rendering framework

Diligent Engine A Modern Cross-Platform Low-Level 3D Graphics Library Diligent Engine is a lightweight cross-platform graphics API abstraction library

Diligent Graphics 2.6k Dec 30, 2022
A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input

GLFW Introduction GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan application development. It provides a simple, platf

GLFW 10k Jan 1, 2023
Low Level Graphics Library (LLGL) is a thin abstraction layer for the modern graphics APIs OpenGL, Direct3D, Vulkan, and Metal

Low Level Graphics Library (LLGL) Documentation NOTE: This repository receives bug fixes only, but no major updates. Pull requests may still be accept

Lukas Hermanns 1.5k Jan 8, 2023
Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.

This project is not actively maintained. NanoVG NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled afte

Mikko Mononen 4.6k Jan 2, 2023
Freecell Solver - a C library for automatically solving Freecell and some other variants of card Solitaire

The Freecell Solver Repository Root README Freecell Solver is an open source (distributed under the MIT/Expat licence) library, written in C, for atte

Shlomi Fish 55 Dec 23, 2022
Pure C math library for 2D and 3D programming

MATHC MATHC is a simple math library for 2D and 3D programming. Features Vectors (2D, 3D and 4D) (integer type and floating-point type) Quaternions Ma

Felipe da Silva 624 Dec 30, 2022
A terminal-based graphics library for both 2D and 3D graphics.

TermGL A terminal-based graphics library for both 2D and 3D graphics. Written in C, created for terminals supporting ANSI escape codes. Table of Conte

null 215 Dec 28, 2022