Initial commit

This commit is contained in:
2026-04-18 11:05:46 +03:00
committed by Mikhail Romanko
commit 415ec3ecd3
24 changed files with 2234 additions and 0 deletions

68
.gitignore vendored Normal file
View File

@@ -0,0 +1,68 @@
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# ---> CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json

56
Box2f.c Normal file
View File

@@ -0,0 +1,56 @@
#include "CgeMath.h"
#include <string.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
void CgeBox2fUnion(const float aMin[2], const float aMax[2],
const float bMin[2], const float bMax[2],
float outMin[2], float outMax[2]) {
CgeVec2fMin(aMin, bMin, outMin);
CgeVec2fMax(aMax, bMax, outMax);
}
int CgeBox2fIntersect(const float aMin[2], const float aMax[2],
const float bMin[2], const float bMax[2],
float outMin[2], float outMax[2]) {
CgeVec2fMax(aMin, bMin, outMin);
CgeVec2fMin(aMax, bMax, outMax);
if (outMin[0] >= outMax[0] || outMin[1] >= outMax[1])
return 0;
return 1;
}
int CgeBox2fContains(const float aMin[2], const float aMax[2],
const float point[2]) {
if (point[0] < aMin[0] || point[1] < aMin[1])
return 0;
if (point[0] > aMax[0] || point[1] > aMax[1])
return 0;
return 1;
}
int CgeBox2fEnclose(const float *points, size_t size, float outMin[2],
float outMax[2]) {
float tmp1[2], tmp2[2];
size_t i;
if (!size)
return 0;
memcpy(tmp1, points, sizeof(tmp1));
memcpy(tmp2, points, sizeof(tmp2));
for (i = 1; i < size; i++) {
CgeVec2fMin(tmp1, points + i * 2, tmp1);
CgeVec2fMax(tmp2, points + i * 2, tmp2);
}
memcpy(outMin, tmp1, sizeof(tmp1));
memcpy(outMax, tmp2, sizeof(tmp2));
return 1;
}

56
Box3f.c Normal file
View File

@@ -0,0 +1,56 @@
#include "CgeMath.h"
#include <string.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
void CgeBox3fUnion(const float aMin[3], const float aMax[3],
const float bMin[3], const float bMax[3],
float outMin[3], float outMax[3]) {
CgeVec3fMin(aMin, bMin, outMin);
CgeVec3fMax(aMax, bMax, outMax);
}
int CgeBox3fIntersect(const float aMin[3], const float aMax[3],
const float bMin[3], const float bMax[3],
float outMin[3], float outMax[3]) {
CgeVec3fMax(aMin, bMin, outMin);
CgeVec3fMin(aMax, bMax, outMax);
if (outMin[0] >= outMax[0] || outMin[1] >= outMax[1] || outMin[2] >= outMax[2])
return 0;
return 1;
}
int CgeBox3fContains(const float aMin[3], const float aMax[3],
const float point[3]) {
if (point[0] < aMin[0] || point[1] < aMin[1] || point[2] < aMin[2])
return 0;
if (point[0] > aMax[0] || point[1] > aMax[1] || point[2] > aMax[2])
return 0;
return 1;
}
int CgeBox3fEnclose(const float *points, size_t size, float outMin[3],
float outMax[3]) {
float tmp1[3], tmp2[3];
size_t i;
if (!size)
return 0;
memcpy(tmp1, points, sizeof(tmp1));
memcpy(tmp2, points, sizeof(tmp2));
for (i = 1; i < size; i++) {
CgeVec3fMin(tmp1, points + i * 3, tmp1);
CgeVec3fMax(tmp2, points + i * 3, tmp2);
}
memcpy(outMin, tmp1, sizeof(tmp1));
memcpy(outMax, tmp2, sizeof(tmp2));
return 1;
}

40
CMakeLists.txt Normal file
View File

@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.10)
project(CgeMath LANGUAGES C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(SOURCES
Box2f.c
Box3f.c
Line.c
Mat3f.c
Mat4f.c
Misc.c
Plane.c
Quat4f.c
Ray2f.c
Ray3f.c
Vec2f.c
Vec2i.c
Vec3f.c
Vec3i.c
Vec4f.c
Vec4i.c
)
set(HEADERS
CgeMath.h
)
add_library(CgeMath STATIC ${SOURCES} ${HEADERS})
target_include_directories(CgeMath PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS CgeMath
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
install(FILES ${HEADERS} DESTINATION include)

230
CgeMath.h Normal file
View File

@@ -0,0 +1,230 @@
#ifndef CGE_MATH_H
#define CGE_MATH_H
#include <stddef.h>
void CgeBox2fUnion(const float aMin[2], const float aMax[2],
const float bMin[2], const float bMax[2],
float outMin[2], float outMax[2]);
int CgeBox2fIntersect(const float aMin[2], const float aMax[2],
const float bMin[2], const float bMax[2],
float outMin[2], float outMax[2]);
int CgeBox2fContains(const float aMin[2], const float aMax[2],
const float point[2]);
int CgeBox2fEnclose(const float *points, size_t size, float outMin[2],
float outMax[2]);
void CgeBox3fUnion(const float aMin[3], const float aMax[3],
const float bMin[3], const float bMax[3],
float outMin[3], float outMax[3]);
int CgeBox3fIntersect(const float aMin[3], const float aMax[3],
const float bMin[3], const float bMax[3],
float outMin[3], float outMax[3]);
int CgeBox3fContains(const float aMin[3], const float aMax[3],
const float point[3]);
int CgeBox3fEnclose(const float *points, size_t size, float outMin[3],
float outMax[3]);
int CgeLineFromPoints(const float a[2], const float b[2], float out[3]);
float CgeLineDistance(const float line[3], const float point[2]);
void CgeLineClosestPoint(const float line[3], const float point[2],
float out[2]);
void CgeMat3fIdentity(float out[9]);
void CgeMat3fAdd(const float a[9], const float b[9], float out[9]);
void CgeMat3fSub(const float a[9], const float b[9], float out[9]);
void CgeMat3fMul(const float a[9], const float b[9], float out[9]);
void CgeMat3fScale(const float a[9], float b, float out[9]);
void CgeMat3fTranspose(const float in[9], float out[9]);
float CgeMat3fTrace(const float in[9]);
float CgeMat3fDet(const float in[9]);
int CgeMat3fInverse(const float in[9], float out[9]);
void CgeMat3fFromScale(float x, float y, float out[9]);
void CgeMat3fFromTranslation(float x, float y, float out[9]);
void CgeMat3fFromRotation(float angle, float out[9]);
void CgeMat3fApplyVec3f(float a[9], float b[3], float out[3]);
void CgeMat3fApplyVec2f(float a[9], float b[2], float out[2]);
void CgeMat4fIdentity(float out[16]);
void CgeMat4fAdd(const float a[16], const float b[16], float out[16]);
void CgeMat4fSub(const float a[16], const float b[16], float out[16]);
void CgeMat4fMul(const float a[16], const float b[16], float out[16]);
void CgeMat4fScale(const float a[16], float b, float out[16]);
void CgeMat4fTranspose(const float in[16], float out[16]);
float CgeMat4fTrace(const float in[16]);
float CgeMat4fDet(const float in[16]);
int CgeMat4fInverse(const float in[16], float out[16]);
void CgeMat4fFromScale(float x, float y, float z, float out[16]);
void CgeMat4fFromTranslation(float x, float y, float z, float out[16]);
void CgeMat4fFromRotationX(float angle, float out[16]);
void CgeMat4fFromRotationY(float angle, float out[16]);
void CgeMat4fFromRotationZ(float angle, float out[16]);
void CgeMat4fFromAxis(const float axis[3], float angle, float out[16]);
void CgeMat4fFromEuler(float roll, float pitch, float yaw, float out[16]);
void CgeMat4fFromQuat4f(const float in[4], float out[16]);
void CgeMat4fFromOrtho(float xMin, float xMax, float yMin, float yMax,
float zMin, float zMax, float out[16]);
void CgeMat4fFromFrustum(float fov, float aspect, float zMin, float zMax,
float out[16]);
void CgeMat4fFromLookAt(const float position[3], const float at[3],
const float up[3], float out[16]);
void CgeMat4fApplyVec4f(const float a[16], const float b[4], float out[4]);
void CgeMat4fApplyVec3f(const float a[16], const float b[3], float out[3]);
float CgeLerpf(float a, float b, float t);
void CgeTriangle3fBarycentric(const float a[3], const float b[3],
const float c[3], const float point[3],
float out[3]);
int CgePlaneFromPoints(const float a[3], const float b[3], const float c[3],
float out[4]);
float CgePlaneDistance(const float plane[4], const float point[3]);
void CgePlaneClosestPoint(const float plane[4], const float point[3],
float out[3]);
#define CgeQuat4fAdd(a, b, out) CgeVec4fAdd(a, b, out)
#define CgeQuat4fSub(a, b, out) CgeVec4fSub(a, b, out)
#define CgeQuat4fScale(a, b, out) CgeVec4fScale(a, b, out)
#define CgeQuat4fNegate(in, out) CgeVec4fNegate(in, out)
#define CgeQuat4fDot(a, b) CgeVec4fDot(a, b)
#define CgeQuat4fLength(in) CgeVec4fLength(in)
#define CgeQuat4fNormal(in, out) CgeVec4fNormal(in, out)
#define CgeQuat4fLerp(a, b, t, out) CgeVec4fLerp(a, b, t, out)
void CgeQuat4fIdentity(float out[4]);
void CgeQuat4fConjugate(const float in[4],float out[4]);
void CgeQuat4fInverse(const float in[4], float out[4]);
void CgeQuat4fMul(const float a[4], const float b[4], float out[4]);
void CgeQuat4fSlerp(const float a[4], const float b[4], float t, float out[4]);
void CgeQuat4fFromEuler(float roll, float pitch, float yaw, float out[4]);
void CgeQuat4fFromAxis(const float axis[3], float angle, float out[4]);
void CgeQuat4fToEuler(const float in[4], float *roll, float *pitch, float *yaw);
void CgeQuat4fToAxis(const float in[4], float axis[3], float *angle);
void CgeQuat4fToMat4f(const float in[4], float out[16]);
int CgeRay2fIntersectLine(const float start[2], const float direction[2],
const float line[3], float *t, float out[2]);
int CgeRay2fIntersectTime(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bDirection[2],
float *time1, float *time2);
int CgeRay2fIntersectRay(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bDirection[2],
float *t, float out[2]);
int CgeRay2fIntersectSegment(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bEnd[2],
float *t, float out[2]);
int CgeSegment2fIntersectLine(const float start[2], const float end[2],
const float line[3], float *t, float out[2]);
int CgeSegment2fIntersectSegment(const float aStart[2], const float aEnd[2],
const float bStart[2], const float bEnd[2],
float *t, float out[2]);
int CgeRay2fIntersectBox2f(const float aStart[2], const float aDirection[2],
const float bMin[2], const float bMax[2],
float *t, float out[2]);
int CgeSegment2fIntersectBox2f(const float aStart[2], const float aEnd[2],
const float bMin[2], const float bMax[2],
float *t, float out[2]);
int CgeRay3fIntersectPlane(const float start[3], const float direction[3],
const float plane[4], float *t, float out[3]);
int CgeRay3fIntersectTriangle(const float start[3], const float direction[3],
const float a[3], const float b[3],
const float c[3], float *t, float out[3]);
int CgeSegment3fIntersectPlane(const float start[3], const float end[3],
const float plane[4], float *t, float out[3]);
int CgeSegment3fIntersectTriangle(const float start[3], const float end[3],
const float a[3], const float b[3],
const float c[3], float *t, float out[3]);
int CgeRay3fIntersectBox3f(const float aStart[3], const float aDirection[3],
const float bMin[3], const float bMax[3],
float *t, float out[3]);
int CgeSegment3fIntersectBox3f(const float aStart[3], const float aEnd[3],
const float bMin[3], const float bMax[3],
float *t, float out[3]);
void CgeVec2fAdd(const float a[2], const float b[2], float out[2]);
void CgeVec2fSub(const float a[2], const float b[2], float out[2]);
void CgeVec2fMul(const float a[2], const float b[2], float out[2]);
void CgeVec2fScale(const float a[2], float b, float out[2]);
void CgeVec2fMulAdd(const float a[2], const float b[2], const float c[2],
float out[2]);
void CgeVec2fNegate(const float in[2], float out[2]);
float CgeVec2fDot(const float a[2], const float b[2]);
float CgeVec2fCross(const float a[2], const float b[2]);
float CgeVec2fLength(const float in[2]);
void CgeVec2fNormal(const float in[2], float out[2]);
float CgeVec2fNormalEx(const float in[2], float out[2]);
void CgeVec2fMin(const float a[2], const float b[2], float out[2]);
void CgeVec2fMax(const float a[2], const float b[2], float out[2]);
void CgeVec2fLerp(const float a[2], const float b[2], float t, float out[2]);
void CgeVec2fProject(const float a[2], const float b[2], float out[2]);
void CgeVec2fBarycentric(const float a[2], const float b[2], const float c[2],
float v, float w, float out[2]);
void CgeVec2iAdd(const int a[2], const int b[2], int out[2]);
void CgeVec2iSub(const int a[2], const int b[2], int out[2]);
void CgeVec2iMul(const int a[2], const int b[2], int out[2]);
void CgeVec2iScale(const int a[2], int b, int out[2]);
void CgeVec2iMulAdd(const int a[2], const int b[2], const int c[2], int out[2]);
void CgeVec2iNegate(const int in[2], int out[2]);
void CgeVec2iMin(const int a[2], const int b[2], int out[2]);
void CgeVec2iMax(const int a[2], const int b[2], int out[2]);
void CgeVec3fAdd(const float a[3], const float b[3], float out[3]);
void CgeVec3fSub(const float a[3], const float b[3], float out[3]);
void CgeVec3fMul(const float a[3], const float b[3], float out[3]);
void CgeVec3fScale(const float a[3], float b, float out[3]);
void CgeVec3fMulAdd(const float a[3], const float b[3], const float c[3],
float out[3]);
void CgeVec3fNegate(const float in[3], float out[3]);
float CgeVec3fDot(const float a[3], const float b[3]);
void CgeVec3fCross(const float a[3], const float b[3], float out[3]);
float CgeVec3fLength(const float in[3]);
void CgeVec3fNormal(const float in[3], float out[3]);
float CgeVec3fNormalEx(const float in[3], float out[3]);
void CgeVec3fMin(const float a[3], const float b[3], float out[3]);
void CgeVec3fMax(const float a[3], const float b[3], float out[3]);
void CgeVec3fLerp(const float a[3], const float b[3], float t, float out[3]);
void CgeVec3fProject(const float a[3], const float b[3], float out[3]);
void CgeVec3fBarycentric(const float a[3], const float b[3], const float c[3],
float v, float w, float out[3]);
void CgeVec3iAdd(const int a[3], const int b[3], int out[3]);
void CgeVec3iSub(const int a[3], const int b[3], int out[3]);
void CgeVec3iMul(const int a[3], const int b[3], int out[3]);
void CgeVec3iScale(const int a[3], int b, int out[3]);
void CgeVec3iMulAdd(const int a[3], const int b[3], const int c[3], int out[3]);
void CgeVec3iNegate(const int in[3], int out[3]);
void CgeVec3iMin(const int a[3], const int b[3], int out[3]);
void CgeVec3iMax(const int a[3], const int b[3], int out[3]);
void CgeVec4fAdd(const float a[4], const float b[4], float out[4]);
void CgeVec4fSub(const float a[4], const float b[4], float out[4]);
void CgeVec4fMul(const float a[4], const float b[4], float out[4]);
void CgeVec4fScale(const float a[4], float b, float out[4]);
void CgeVec4fMulAdd(const float a[4], const float b[4], const float c[4],
float out[4]);
void CgeVec4fNegate(const float in[4], float out[4]);
float CgeVec4fDot(const float a[4], const float b[4]);
float CgeVec4fLength(const float in[4]);
void CgeVec4fNormal(const float in[4], float out[4]);
float CgeVec4fNormalEx(const float in[4], float out[4]);
void CgeVec4fMin(const float a[4], const float b[4], float out[4]);
void CgeVec4fMax(const float a[4], const float b[4], float out[4]);
void CgeVec4fLerp(const float a[4], const float b[4], float t, float out[4]);
void CgeVec4fProject(const float a[4], const float b[4], float out[4]);
void CgeVec4fBarycentric(const float a[4], const float b[4], const float c[4],
float v, float w, float out[4]);
void CgeVec4iAdd(const int a[4], const int b[4], int out[4]);
void CgeVec4iSub(const int a[4], const int b[4], int out[4]);
void CgeVec4iMul(const int a[4], const int b[4], int out[4]);
void CgeVec4iScale(const int a[4], int b, int out[4]);
void CgeVec4iMulAdd(const int a[4], const int b[4], const int c[4], int out[4]);
void CgeVec4iNegate(const int in[4], int out[4]);
void CgeVec4iMin(const int a[4], const int b[4], int out[4]);
void CgeVec4iMax(const int a[4], const int b[4], int out[4]);
#endif /* CGE_MATH_H */

12
LICENSE Normal file
View File

@@ -0,0 +1,12 @@
Copyright (C) 2026 by blankhex me@blankhex.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

30
Line.c Normal file
View File

@@ -0,0 +1,30 @@
#include "CgeMath.h"
#include <string.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
int CgeLineFromPoints(const float a[2], const float b[2], float out[3]) {
float tmp[2];
tmp[0] = a[1] - b[1];
tmp[1] = b[0] - a[0];
if (CgeVec2fNormalEx(tmp, tmp) < EPSILON)
return 0;
out[2] = CgeVec2fDot(tmp, a);
memcpy(out, tmp, sizeof(tmp));
return 1;
}
float CgeLineDistance(const float line[3], const float point[2]) {
return CgeVec2fDot(line, point) - line[2];
}
void CgeLineClosestPoint(const float line[3], const float point[2],
float out[2]) {
float tmp[2];
CgeVec2fScale(line, CgeLineDistance(line, point), tmp);
CgeVec2fSub(point, tmp, out);
}

24
Makefile.mingw Normal file
View File

@@ -0,0 +1,24 @@
# MinGW Makefile for CgeMath
CC = gcc
AR = ar
CFLAGS = -std=c99 -O2 -Wall -Wextra
ARFLAGS = rcs
TARGET = libCgeMath.a
SOURCES = Box2f.c Box3f.c Line.c Mat3f.c Mat4f.c Misc.c Plane.c Quat4f.c \
Ray2f.c Ray3f.c Vec2f.c Vec2i.c Vec3f.c Vec3i.c Vec4f.c Vec4i.c
OBJECTS = $(SOURCES:.c=.o)
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(AR) $(ARFLAGS) $@ $^
%.o: %.c CgeMath.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
del $(OBJECTS) $(TARGET) 2>nul || exit 0

34
Makefile.posix Normal file
View File

@@ -0,0 +1,34 @@
# POSIX Makefile for CgeMath
CC = gcc
AR = ar
CFLAGS = -std=c99 -O2 -Wall -Wextra -fPIC
ARFLAGS = rcs
TARGET = libCgeMath.a
SOURCES = Box2f.c Box3f.c Line.c Mat3f.c Mat4f.c Misc.c Plane.c Quat4f.c \
Ray2f.c Ray3f.c Vec2f.c Vec2i.c Vec3f.c Vec3i.c Vec4f.c Vec4i.c
OBJECTS = $(SOURCES:.c=.o)
.PHONY: all clean install
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(AR) $(ARFLAGS) $@ $^
%.o: %.c CgeMath.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJECTS) $(TARGET)
install: $(TARGET)
cp $(TARGET) /usr/local/lib/
cp CgeMath.h /usr/local/include/
ldconfig || echo "Run ldconfig manually if needed"
uninstall:
rm -f /usr/local/lib/libCgeMath.a
rm -f /usr/local/include/CgeMath.h
ldconfig || true

24
Makefile.win32 Normal file
View File

@@ -0,0 +1,24 @@
# Makefile.win32 for MSVC (NMake)
# Usage: Open "x86 Native Tools Command Prompt", then:
# nmake -f Makefile.win32
CC = cl
LIB = lib
CFLAGS = /c /nologo /W3 /O2
LIBFLAGS = /nologo
TARGET = CgeMath.lib
SOURCES = Box2f.c Box3f.c Line.c Mat3f.c Mat4f.c Misc.c Plane.c Quat4f.c \
Ray2f.c Ray3f.c Vec2f.c Vec2i.c Vec3f.c Vec3i.c Vec4f.c Vec4i.c
OBJECTS = $(SOURCES:.c=.obj)
$(TARGET): $(OBJECTS)
$(LIB) $(LIBFLAGS) /OUT:$(TARGET) $(OBJECTS)
{.}.c{}.obj:
$(CC) $(CFLAGS) /Fo$@ $<
clean:
del $(OBJECTS) $(TARGET) 2>nul
.PHONY: clean

167
Mat3f.c Normal file
View File

@@ -0,0 +1,167 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
#define SET_ROW(row, val) row[0] = row[1] = row[2] = val
void CgeMat3fIdentity(float out[9]) {
static const float ident[9] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
memcpy(out, ident, sizeof(ident));
}
void CgeMat3fAdd(const float a[9], const float b[9], float out[9]) {
CgeVec3fAdd(&a[0], &b[0], &out[0]);
CgeVec3fAdd(&a[3], &b[3], &out[3]);
CgeVec3fAdd(&a[6], &b[6], &out[6]);
}
void CgeMat3fSub(const float a[9], const float b[9], float out[9]) {
CgeVec3fSub(&a[0], &b[0], &out[0]);
CgeVec3fSub(&a[3], &b[3], &out[3]);
CgeVec3fSub(&a[6], &b[6], &out[6]);
}
void CgeMat3fMul(const float a[9], const float b[9], float out[9]) {
float tmp[9], row[3];
SET_ROW(row, b[0]); CgeVec3fMul(&a[0], row, &tmp[0]);
SET_ROW(row, b[1]); CgeVec3fMulAdd(&a[3], row, &tmp[0], &tmp[0]);
SET_ROW(row, b[2]); CgeVec3fMulAdd(&a[6], row, &tmp[0], &tmp[0]);
SET_ROW(row, b[3]); CgeVec3fMul(&a[0], row, &tmp[3]);
SET_ROW(row, b[4]); CgeVec3fMulAdd(&a[3], row, &tmp[3], &tmp[3]);
SET_ROW(row, b[5]); CgeVec3fMulAdd(&a[6], row, &tmp[3], &tmp[3]);
SET_ROW(row, b[6]); CgeVec3fMul(&a[0], row, &tmp[6]);
SET_ROW(row, b[7]); CgeVec3fMulAdd(&a[3], row, &tmp[6], &tmp[6]);
SET_ROW(row, b[8]); CgeVec3fMulAdd(&a[6], row, &tmp[6], &tmp[6]);
memcpy(out, tmp, sizeof(tmp));
}
void CgeMat3fScale(const float a[9], float b, float out[9]) {
CgeVec3fScale(&a[0], b, &out[0]);
CgeVec3fScale(&a[3], b, &out[3]);
CgeVec3fScale(&a[6], b, &out[6]);
}
void CgeMat3fTranspose(const float in[9], float out[9]) {
float tmp[9];
tmp[0] = in[0]; tmp[3] = in[1]; tmp[6] = in[2];
tmp[1] = in[3]; tmp[4] = in[4]; tmp[7] = in[5];
tmp[2] = in[6]; tmp[5] = in[7]; tmp[8] = in[8];
memcpy(out, tmp, sizeof(tmp));
}
float CgeMat3fTrace(const float in[9]) {
return in[0] + in[4] + in[8];
}
float CgeMat3fDet(const float in[9]) {
float a, b, c, result;
a = in[4] * in[8] - in[7] * in[5];
b = in[1] * in[8] - in[7] * in[2];
c = in[1] * in[5] - in[4] * in[2];
result = 0.0f;
result += in[0] * a;
result -= in[3] * b;
result += in[6] * c;
return result;
}
int CgeMat3fInverse(const float in[9], float out[9]) {
float a, b, c, det;
float tmp[16];
a = in[4] * in[8] - in[7] * in[5];
b = in[1] * in[8] - in[7] * in[2];
c = in[1] * in[5] - in[4] * in[2];
tmp[0] = a;
tmp[1] = -b;
tmp[2] = c;
det = 0.0f;
det += in[0] * tmp[0];
det += in[3] * tmp[1];
det += in[6] * tmp[2];
if (fabsf(det) < EPSILON)
return 0;
a = in[3] * in[8] - in[6] * in[5];
b = in[0] * in[8] - in[6] * in[2];
c = in[0] * in[5] - in[3] * in[2];
tmp[3] = -a;
tmp[4] = b;
tmp[5] = -c;
a = in[3] * in[7] - in[6] * in[4];
b = in[0] * in[7] - in[6] * in[1];
c = in[0] * in[4] - in[3] * in[1];
tmp[6] = a;
tmp[7] = -b;
tmp[8] = c;
CgeMat3fScale(tmp, 1.0f / det, out);
return 1;
}
void CgeMat3fFromScale(float x, float y, float out[9]) {
CgeMat3fIdentity(out);
out[0] = x;
out[4] = y;
}
void CgeMat3fFromTranslation(float x, float y, float out[9]) {
CgeMat3fIdentity(out);
out[6] = x;
out[7] = y;
}
void CgeMat3fFromRotation(float angle, float out[9]) {
float c, s;
c = cosf(angle);
s = sinf(angle);
CgeMat3fIdentity(out);
out[0] = c;
out[1] = s;
out[3] = -s;
out[4] = c;
}
void CgeMat3fApplyVec3f(float a[9], float b[3], float out[3]) {
float tmp[3], row[3];
SET_ROW(row, b[0]); CgeVec3fMul(&a[0], row, tmp);
SET_ROW(row, b[1]); CgeVec3fMulAdd(&a[3], row, tmp, tmp);
SET_ROW(row, b[2]); CgeVec3fMulAdd(&a[6], row, tmp, tmp);
memcpy(out, tmp, sizeof(tmp));
}
void CgeMat3fApplyVec2f(float a[9], float b[2], float out[2]) {
float tmp[3], row[3];
SET_ROW(row, b[0]); CgeVec3fMul(&a[0], row, tmp);
SET_ROW(row, b[1]); CgeVec3fMulAdd(&a[3], row, tmp, tmp);
SET_ROW(row, 1.0f); CgeVec3fMulAdd(&a[6], row, tmp, tmp);
memcpy(out, tmp, sizeof(float) * 2);
}

362
Mat4f.c Normal file
View File

@@ -0,0 +1,362 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
#define SET_ROW(row, val) row[0] = row[1] = row[2] = row[3] = val
void CgeMat4fIdentity(float out[16]) {
const float ident[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
memcpy(out, ident, sizeof(ident));
}
void CgeMat4fAdd(const float a[16], const float b[16], float out[16]) {
CgeVec4fAdd(&a[0], &b[0], &out[0]);
CgeVec4fAdd(&a[4], &b[4], &out[4]);
CgeVec4fAdd(&a[8], &b[8], &out[8]);
CgeVec4fAdd(&a[12], &b[12], &out[12]);
}
void CgeMat4fSub(const float a[16], const float b[16], float out[16]) {
CgeVec4fSub(&a[0], &b[0], &out[0]);
CgeVec4fSub(&a[4], &b[4], &out[4]);
CgeVec4fSub(&a[8], &b[8], &out[8]);
CgeVec4fSub(&a[12], &b[12], &out[12]);
}
void CgeMat4fMul(const float a[16], const float b[16], float out[16]) {
float tmp[16], row[4];
SET_ROW(row, b[0]); CgeVec4fMul(&a[0], row, &tmp[0]);
SET_ROW(row, b[1]); CgeVec4fMulAdd(&a[4], row, &tmp[0], &tmp[0]);
SET_ROW(row, b[2]); CgeVec4fMulAdd(&a[8], row, &tmp[0], &tmp[0]);
SET_ROW(row, b[3]); CgeVec4fMulAdd(&a[12], row, &tmp[0], &tmp[0]);
SET_ROW(row, b[4]); CgeVec4fMul(&a[0], row, &tmp[4]);
SET_ROW(row, b[5]); CgeVec4fMulAdd(&a[4], row, &tmp[4], &tmp[4]);
SET_ROW(row, b[6]); CgeVec4fMulAdd(&a[8], row, &tmp[4], &tmp[4]);
SET_ROW(row, b[7]); CgeVec4fMulAdd(&a[12], row, &tmp[4], &tmp[4]);
SET_ROW(row, b[8]); CgeVec4fMul(&a[0], row, &tmp[8]);
SET_ROW(row, b[9]); CgeVec4fMulAdd(&a[4], row, &tmp[8], &tmp[8]);
SET_ROW(row, b[10]); CgeVec4fMulAdd(&a[8], row, &tmp[8], &tmp[8]);
SET_ROW(row, b[11]); CgeVec4fMulAdd(&a[12], row, &tmp[8], &tmp[8]);
SET_ROW(row, b[12]); CgeVec4fMul(&a[0], row, &tmp[12]);
SET_ROW(row, b[13]); CgeVec4fMulAdd(&a[4], row, &tmp[12], &tmp[12]);
SET_ROW(row, b[14]); CgeVec4fMulAdd(&a[8], row, &tmp[12], &tmp[12]);
SET_ROW(row, b[15]); CgeVec4fMulAdd(&a[12], row, &tmp[12], &tmp[12]);
memcpy(out, tmp, sizeof(tmp));
}
void CgeMat4fScale(const float a[16], float b, float out[16]) {
CgeVec4fScale(&a[0], b, &out[0]);
CgeVec4fScale(&a[4], b, &out[4]);
CgeVec4fScale(&a[8], b, &out[8]);
CgeVec4fScale(&a[12], b, &out[12]);
}
void CgeMat4fTranspose(const float in[16], float out[16]) {
float tmp[16];
tmp[0] = in[0]; tmp[4] = in[1]; tmp[8] = in[2]; tmp[12] = in[3];
tmp[1] = in[4]; tmp[5] = in[5]; tmp[9] = in[6]; tmp[13] = in[7];
tmp[2] = in[8]; tmp[6] = in[9]; tmp[10] = in[10]; tmp[14] = in[11];
tmp[3] = in[12]; tmp[7] = in[13]; tmp[11] = in[14]; tmp[15] = in[15];
memcpy(out, tmp, sizeof(tmp));
}
float CgeMat4fTrace(const float in[16]) {
return in[0] + in[5] + in[10] + in[15];
}
float CgeMat4fDet(const float in[16]) {
float a, b, c, d, e, f, result;
a = in[2] * in[7] - in[3] * in[6];
b = in[2] * in[11] - in[3] * in[10];
c = in[2] * in[15] - in[3] * in[14];
d = in[6] * in[11] - in[7] * in[10];
e = in[6] * in[15] - in[7] * in[14];
f = in[10] * in[15] - in[11] * in[14];
result = 0.0f;
result += in[0] * (in[5] * f - in[9] * e + in[13] * d);
result -= in[4] * (in[1] * f - in[9] * c + in[13] * b);
result += in[8] * (in[1] * e - in[5] * c + in[13] * a);
result -= in[12] * (in[1] * d - in[5] * b + in[9] * a);
return result;
}
int CgeMat4fInverse(const float in[16], float out[16]) {
float a, b, c, d, e, f, det;
float tmp[16];
a = in[2] * in[7] - in[3] * in[6];
b = in[2] * in[11] - in[3] * in[10];
c = in[2] * in[15] - in[3] * in[14];
d = in[6] * in[11] - in[7] * in[10];
e = in[6] * in[15] - in[7] * in[14];
f = in[10] * in[15] - in[11] * in[14];
tmp[0] = (in[5] * f - in[9] * e + in[13] * d);
tmp[1] = -(in[1] * f - in[9] * c + in[13] * b);
tmp[2] = (in[1] * e - in[5] * c + in[13] * a);
tmp[3] = -(in[1] * d - in[5] * b + in[9] * a);
det = 0.0f;
det += in[0] * tmp[0];
det += in[4] * tmp[1];
det += in[8] * tmp[2];
det += in[12] * tmp[3];
if (fabsf(det) < EPSILON)
return 0;
tmp[4] = -(in[4] * f - in[8] * e + in[12] * d);
tmp[5] = (in[0] * f - in[8] * c + in[12] * b);
tmp[6] = -(in[0] * e - in[4] * c + in[12] * a);
tmp[7] = (in[0] * d - in[4] * b + in[8] * a);
a = in[1] * in[7] - in[3] * in[5];
b = in[1] * in[11] - in[3] * in[9];
c = in[1] * in[15] - in[3] * in[13];
d = in[5] * in[11] - in[7] * in[9];
e = in[5] * in[15] - in[7] * in[13];
f = in[9] * in[15] - in[11] * in[13];
tmp[8] = (in[4] * f - in[8] * e + in[12] * d);
tmp[9] = -(in[0] * f - in[8] * c + in[12] * b);
tmp[10] = (in[0] * e - in[4] * c + in[12] * a);
tmp[11] = -(in[0] * d - in[4] * b + in[8] * a);
a = in[1] * in[6] - in[2] * in[5];
b = in[1] * in[10] - in[2] * in[9];
c = in[1] * in[14] - in[2] * in[13];
d = in[5] * in[10] - in[6] * in[9];
e = in[5] * in[14] - in[6] * in[13];
f = in[9] * in[14] - in[10] * in[13];
tmp[12] = -(in[4] * f - in[8] * e + in[12] * d);
tmp[13] = (in[0] * f - in[8] * c + in[12] * b);
tmp[14] = -(in[0] * e - in[4] * c + in[12] * a);
tmp[15] = (in[0] * d - in[4] * b + in[8] * a);
CgeMat4fScale(tmp, 1.0f / det, out);
return 1;
}
void CgeMat4fFromScale(float x, float y, float z, float out[16]) {
CgeMat4fIdentity(out);
out[0] = x;
out[5] = y;
out[10] = z;
}
void CgeMat4fFromTranslation(float x, float y, float z, float out[16]) {
CgeMat4fIdentity(out);
out[12] = x;
out[13] = y;
out[14] = z;
}
void CgeMat4fFromRotationX(float angle, float out[16]) {
float c, s;
c = cosf(angle);
s = sinf(angle);
CgeMat4fIdentity(out);
out[5] = c;
out[6] = s;
out[9] = -s;
out[10] = c;
}
void CgeMat4fFromRotationY(float angle, float out[16]) {
float c, s;
c = cosf(angle);
s = sinf(angle);
CgeMat4fIdentity(out);
out[0] = c;
out[2] = -s;
out[8] = s;
out[10] = c;
}
void CgeMat4fFromRotationZ(float angle, float out[16]) {
float c, s;
c = cosf(angle);
s = sinf(angle);
CgeMat4fIdentity(out);
out[0] = c;
out[1] = s;
out[4] = -s;
out[5] = c;
}
void CgeMat4fFromAxis(const float axis[3], float angle, float out[16]) {
float x, y, z, length;
float c, s, moc, xx, xy, xz, yy, yz, zz;
length = CgeVec3fLength(axis);
CgeMat4fIdentity(out);
if (fabsf(length) < EPSILON)
return;
x = axis[0] / length;
y = axis[1] / length;
z = axis[2] / length;
c = cosf(angle);
s = sinf(angle);
moc = 1.0f - c;
xx = x * x;
xy = x * y;
xz = x * z;
yy = y * y;
yz = y * z;
zz = z * z;
out[0] = c + xx * moc;
out[1] = xy * moc + z * s;
out[2] = xz * moc - y * s;
out[4] = xy * moc - z * s;
out[5] = c + yy * moc;
out[6] = yz * moc + x * s;
out[8] = xz * moc + y * s;
out[9] = yz * moc - x * s;
out[10] = c + zz * moc;
}
void CgeMat4fFromEuler(float roll, float pitch, float yaw, float out[16]) {
float rs, rc, ys, yc, ps, pc;
rs = sinf(roll);
rc = cosf(roll);
ps = sinf(pitch);
pc = cosf(pitch);
ys = sinf(yaw);
yc = cosf(yaw);
CgeMat4fIdentity(out);
out[0] = pc * yc;
out[1] = pc * ys;
out[2] = -ps;
out[4] = ps * rs * yc - rc * ys;
out[5] = ps * rs * ys + rc * yc;
out[6] = pc * rs;
out[8] = rs * ys + ps * rc * yc;
out[9] = ps * rc * ys - rs * yc;
out[10] = pc * rc;
}
void CgeMat4fFromQuat4f(const float in[4], float out[16]) {
CgeQuat4fToMat4f(in, out);
}
void CgeMat4fFromOrtho(float xMin, float xMax, float yMin, float yMax,
float zMin, float zMax, float out[16]) {
float dx, dy, dz;
dx = xMax - xMin;
dy = yMax - yMin;
dz = zMax - zMin;
CgeMat4fIdentity(out);
out[0] = 2.0f / dx;
out[5] = 2.0f / dy;
out[10] = -2.0f / dz;
out[12] = -(xMax + xMin) / dx;
out[13] = -(yMax + yMin) / dy;
out[14] = -(zMax + zMin) / dz;
}
void CgeMat4fFromFrustum(float fov, float aspect, float zMin, float zMax,
float out[16]) {
float t, dz;
dz = zMax - zMin;
t = tanf(fov / 2.0f);
CgeMat4fIdentity(out);
out[0] = 1.0f / (aspect * t);
out[5] = 1.0f / t;
out[10] = -(zMax + zMin) / dz;
out[11] = -1.0f;
out[14] = -(2.0f * zMax * zMin) / dz;
out[15] = 0.0f;
}
void CgeMat4fFromLookAt(const float position[3], const float at[3],
const float up[3], float out[16]) {
float cameraDir[3], cameraRight[3], cameraUp[3];
CgeVec3fSub(position, at, cameraDir);
CgeVec3fNormal(cameraDir, cameraDir);
CgeVec3fCross(up, cameraDir, cameraRight);
CgeVec3fNormal(cameraRight, cameraRight);
CgeVec3fCross(cameraDir, cameraRight, cameraUp);
out[0] = cameraRight[0];
out[1] = cameraUp[0];
out[2] = cameraDir[0];
out[3] = 0.0f;
out[4] = cameraRight[1];
out[5] = cameraUp[1];
out[6] = cameraDir[1];
out[7] = 0.0f;
out[8] = cameraRight[2];
out[9] = cameraUp[2];
out[10] = cameraDir[2];
out[11] = 0.0f;
out[12] = -CgeVec3fDot(cameraRight, position);
out[13] = -CgeVec3fDot(cameraUp, position);
out[14] = -CgeVec3fDot(cameraDir, position);
out[15] = 1.0f;
}
void CgeMat4fApplyVec4f(const float a[16], const float b[4], float out[4]) {
float tmp[4], row[4];
SET_ROW(row, b[0]); CgeVec4fMul(&a[0], row, tmp);
SET_ROW(row, b[1]); CgeVec4fMulAdd(&a[4], row, tmp, tmp);
SET_ROW(row, b[2]); CgeVec4fMulAdd(&a[8], row, tmp, tmp);
SET_ROW(row, b[3]); CgeVec4fMulAdd(&a[12], row, tmp, tmp);
memcpy(out, tmp, sizeof(tmp));
}
void CgeMat4fApplyVec3f(const float a[16], const float b[3], float out[3]) {
float tmp[4], row[4];
SET_ROW(row, b[0]); CgeVec4fMul(&a[0], row, tmp);
SET_ROW(row, b[1]); CgeVec4fMulAdd(&a[4], row, tmp, tmp);
SET_ROW(row, b[2]); CgeVec4fMulAdd(&a[8], row, tmp, tmp);
SET_ROW(row, 1.0f); CgeVec4fMulAdd(&a[12], row, tmp, tmp);
memcpy(out, tmp, sizeof(float) * 3);
}

27
Misc.c Normal file
View File

@@ -0,0 +1,27 @@
#include "CgeMath.h"
float CgeLerpf(float a, float b, float t) {
return a + (b - a) * t;
}
void CgeTriangle3fBarycentric(const float a[3], const float b[3],
const float c[3], const float point[3],
float out[3]) {
float tmp1[3], tmp2[3], tmp3[3];
float t11, t12, t22, t31, t32, denom;
CgeVec3fSub(b, a, tmp1);
CgeVec3fSub(c, a, tmp2);
CgeVec3fSub(point, a, tmp3);
t11 = CgeVec3fDot(tmp1, tmp1);
t12 = CgeVec3fDot(tmp1, tmp2);
t22 = CgeVec3fDot(tmp2, tmp2);
t31 = CgeVec3fDot(tmp3, tmp1);
t32 = CgeVec3fDot(tmp3, tmp2);
denom = 1.0f / (t11 * t22 - t12 * t12);
out[1] = (t22 * t31 - t12 * t32) * denom;
out[2] = (t11 * t32 - t12 * t31) * denom;
out[0] = 1.0f - out[1] - out[2];
}

32
Plane.c Normal file
View File

@@ -0,0 +1,32 @@
#include "CgeMath.h"
#include <string.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
int CgePlaneFromPoints(const float a[3], const float b[3], const float c[3],
float out[4]) {
float tmp1[3], tmp2[3];
CgeVec3fSub(b, a, tmp1);
CgeVec3fSub(c, a, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fNormalEx(tmp1, tmp1) < EPSILON)
return 0;
out[3] = CgeVec3fDot(a, tmp1);
memcpy(out, tmp1, sizeof(tmp1));
return 1;
}
float CgePlaneDistance(const float plane[4], const float point[3]) {
return CgeVec3fDot(plane, point) - plane[3];
}
void CgePlaneClosestPoint(const float plane[4], const float point[3],
float out[3]) {
float tmp[3];
CgeVec3fScale(plane, CgePlaneDistance(plane, point), tmp);
CgeVec3fSub(point, tmp, out);
}

160
Quat4f.c Normal file
View File

@@ -0,0 +1,160 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
void CgeQuat4fIdentity(float out[4]) {
static const float ident[4] = {0.0f, 0.0f, 0.0f, 1.0f};
memcpy(out, ident, sizeof(ident));
}
void CgeQuat4fConjugate(const float in[4], float out[4]) {
out[0] = -in[0];
out[1] = -in[1];
out[2] = -in[2];
out[3] = in[3];
}
void CgeQuat4fInverse(const float in[4], float out[4]) {
float dot;
dot = CgeVec4fDot(in, in);
CgeQuat4fConjugate(in, out);
CgeQuat4fScale(out, 1.0f / dot, out);
}
void CgeQuat4fMul(const float a[4], const float b[4], float out[4]) {
float tmp1[4], tmp2[4], tmp3[4];
float w;
w = a[3] * b[3] - CgeVec3fDot(a, b);
CgeVec4fScale(a, b[3], tmp1);
CgeVec4fScale(b, a[3], tmp2);
CgeVec3fCross(a, b, tmp3);
CgeVec4fAdd(tmp1, tmp2, out);
CgeVec4fAdd(tmp3, out, out);
out[3] = w;
}
void CgeQuat4fSlerp(const float a[4], const float b[4], float t, float out[4]) {
float angle, denom;
float from[4], to[4];
angle = acosf(CgeVec4fDot(a, b));
if (fabsf(angle) < EPSILON) {
CgeVec4fLerp(a, b, t, out);
return;
}
denom = 1.0f / sinf(angle);
CgeVec4fScale(a, sinf((1 - t) * angle) * denom, from);
CgeVec4fScale(b, sinf(t * angle) * denom, to);
CgeVec4fAdd(from, to, out);
}
void CgeQuat4fFromEuler(float roll, float pitch, float yaw, float out[4]) {
float cr, cp, cy, sr, sp, sy;
cr = cosf(roll / 2.0f);
cp = cosf(pitch / 2.0f);
cy = cosf(yaw / 2.0f);
sr = sinf(roll / 2.0f);
sp = sinf(pitch / 2.0f);
sy = sinf(yaw / 2.0f);
out[0] = sr * cp * cy - cr * sp * sy;
out[1] = cr * sp * cy + sr * cp * sy;
out[2] = cr * cp * sy - sr * sp * cy;
out[3] = cr * cp * cy + sr * sp * sy;
}
void CgeQuat4fFromAxis(const float axis[3], float angle, float out[4]) {
float c, s;
c = cosf(angle / 2.0f);
s = sinf(angle / 2.0f);
out[0] = axis[0] * s;
out[1] = axis[1] * s;
out[2] = axis[2] * s;
out[3] = c;
}
void CgeQuat4fToEuler(const float in[4], float *roll, float *pitch,
float *yaw) {
float ww, xw, yw, zw, xx, xy, xz, yy, yz, zz, angle;
xx = in[0] * in[0];
xy = in[0] * in[1];
xz = in[0] * in[2];
xw = in[0] * in[3];
yy = in[1] * in[1];
yz = in[1] * in[2];
yw = in[1] * in[3];
zz = in[2] * in[2];
zw = in[2] * in[3];
ww = in[3] * in[3];
angle = 2.0f * (yw - xz);
if (angle > 1.0f)
angle = 1.0f;
if (angle < -1.0f)
angle = -1.0f;
*pitch = asinf(angle);
if (fabsf(*pitch - (PI / 2.0f)) < EPSILON) {
*roll = 0.0f;
*yaw = -2.0f * atan2f(in[0], in[3]);
} else if (fabsf(*pitch - (PI / -2.0f)) < EPSILON) {
*roll = 0.0f;
*yaw = 2.0f * atan2f(in[0], in[3]);
} else {
*roll = atan2f(2.0f * (xw + yz), ww - xx - yy + zz);
*yaw = atan2f(2.0f * (zw + xy), ww + xx - yy - zz);
}
}
void CgeQuat4fToAxis(const float in[4], float axis[3], float *angle) {
*angle = 2.0f * acosf(in[3]);
if (fabsf(*angle) < EPSILON) {
axis[0] = 1.0f;
axis[1] = 0.0f;
axis[2] = 0.0f;
} else {
float tmp;
tmp = sqrtf(1.0f - in[3] * in[3]);
axis[0] = in[0] / tmp;
axis[1] = in[1] / tmp;
axis[2] = in[2] / tmp;
}
}
void CgeQuat4fToMat4f(const float in[4], float out[16]) {
float xx, xy, xz, xw, yy, yz, yw, zz, zw;
xx = in[0] * in[0];
xy = in[0] * in[1];
xz = in[0] * in[2];
xw = in[0] * in[3];
yy = in[1] * in[1];
yz = in[1] * in[2];
yw = in[1] * in[3];
zz = in[2] * in[2];
zw = in[2] * in[3];
CgeMat4fIdentity(out);
out[0] = 1.0f - 2.0f * (yy + zz);
out[1] = 2.0f * (xy + zw);
out[2] = 2.0f * (xz - yw);
out[4] = 2.0f * (xy - zw);
out[5] = 1.0f - 2.0f * (xx + zz);
out[6] = 2.0f * (yz + xw);
out[8] = 2.0f * (xz + yw);
out[9] = 2.0f * (yz - xw);
out[10] = 1.0f - 2.0f * (xx + yy);
}

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
# CgeMath - Lightweight Math Library for C
A compact, dependency-free C library for 2D/3D math, linear algebra, and
computational geometry operations.
## Features
- 2D/3D vector operations: addition, subtraction, scaling, dot product, cross product
- Vector normalization, length computation, linear interpolation (lerp)
- 3x3 and 4x4 matrix operations: multiplication, addition, transpose, inverse, determinant
- Matrix utilities: identity, scaling, translation, rotation (axis and Euler)
- Projection matrices: orthographic, frustum, perspective from FOV
- View matrix from position, target, and up vector
- Quaternion operations: multiplication, conjugate, inverse, slerp, lerp
- Quaternion to/from rotation matrix and Euler angles
- Axis-aligned bounding box (AABB) operations in 2D and 3D: union, intersection, containment
- Point enclosure: compute bounding box from point set
- Line and plane geometry: construction from points, distance to point, closest point
- Ray, segment, and line intersection tests in 2D and 3D
- Ray-triangle and segment-triangle intersection
- Barycentric coordinate computation for 2D and 3D triangles
- Integer vector operations for 2D, 3D, 4D: add, subtract, min, max
## Build Systems
- CMake - supports Linux, macOS, Windows (MSVC, MinGW)
- Makefile.posix - for GCC/Clang on POSIX systems
- Makefile.mingw - for MinGW on Windows
- Makefile.win32 - for MSVC with NMake
Builds a static library. No shared library or external dependencies.
## Usage Example
```c
#include "CgeMath.h"
#include <stdio.h>
int main() {
float pos[] = {1.0f, 0.0f, 0.0f};
float scale[] = {2.0f, 2.0f, 2.0f};
float mat[16], result[3];
CgeMat4fIdentity(mat);
CgeMat4fFromScale(scale[0], scale[1], scale[2], mat);
CgeMat4fApplyVec3f(mat, pos, result);
printf("Transformed: (%f, %f, %f)\n",
result[0], result[1], result[2]);
return 0;
}
```
## Portability
- Written in C89 + stdint.h
- No dynamic memory allocation
- No external dependencies
## License
0BSD - a permissive license with no attribution required.

193
Ray2f.c Normal file
View File

@@ -0,0 +1,193 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
int CgeRay2fIntersectLine(const float start[2], const float direction[2],
const float line[3], float *t, float out[2]) {
float tmp1[2];
float denom, time;
/* Calculate intersection time */
denom = CgeVec2fDot(direction, line);
time = (line[2] - CgeVec2fDot(line, start)) / denom;
/* Check for ray/plane parallel to each other or point is behing the ray. */
if (fabsf(denom) < EPSILON || time < 0.0f)
return 0;
/* Compute intersection point */
CgeVec2fScale(direction, time, tmp1);
CgeVec2fAdd(start, tmp1, out);
*t = time;
return 1;
}
int CgeRay2fIntersectTime(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bDirection[2],
float *time1, float *time2) {
float tmp1[2], tmp2[2], tmp3[2];
float denom;
/* Rotate directions by 90 degrees and caluclate denom */
tmp1[0] = -aDirection[1]; tmp1[1] = aDirection[0];
tmp2[0] = -bDirection[1]; tmp2[1] = bDirection[0];
denom = CgeVec2fDot(tmp1, bDirection);
if (fabsf(denom) < EPSILON)
return 0;
/* Calculate segments offset and intersection times */
CgeVec2fSub(aStart, bStart, tmp3);
*time1 = CgeVec2fDot(tmp3, tmp2) / denom;
*time2 = CgeVec2fDot(tmp3, tmp1) / denom;
return 1;
}
int CgeRay2fIntersectRay(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bDirection[2],
float *t, float out[2]) {
float tmp[2];
float time1, time2;
if (CgeRay2fIntersectTime(aStart, aDirection, bStart, bDirection, &time1, &time2))
return 0;
if (time1 < 0.0f || time2 < 0.0f)
return 0;
CgeVec2fScale(aDirection, time1, tmp);
CgeVec2fAdd(aStart, tmp, out);
*t = time1;
return 1;
}
int CgeRay2fIntersectSegment(const float aStart[2], const float aDirection[2],
const float bStart[2], const float bEnd[2],
float *t, float out[2]) {
float tmp[2];
float time1, time2;
CgeVec2fSub(bEnd, bStart, tmp);
if (CgeRay2fIntersectTime(aStart, aDirection, bStart, tmp, &time1, &time2))
return 0;
if (time1 < 0.0f || time2 < 0.0f || time2 > 1.0f)
return 0;
CgeVec2fScale(aDirection, time1, tmp);
CgeVec2fAdd(aStart, tmp, out);
*t = time1;
return 1;
}
int CgeSegment2fIntersectLine(const float start[2], const float end[2],
const float line[3], float *t, float out[2]) {
float tmp[2];
float denom, time;
/* Calculate intersection time */
CgeVec2fSub(end, start, tmp);
denom = CgeVec2fDot(tmp, line);
time = (line[2] - CgeVec2fDot(line, start)) / denom;
/* Check for ray/plane parallel to each other or point is behing the ray. */
if (fabsf(denom) < EPSILON || time < 0.0f || time > 1.0f)
return 0;
/* Compute intersection point */
CgeVec2fScale(tmp, time, tmp);
CgeVec2fAdd(start, tmp, out);
*t = time;
return 1;
}
int CgeSegment2fIntersectSegment(const float aStart[2], const float aEnd[2],
const float bStart[2], const float bEnd[2],
float *t, float out[2]) {
float tmp1[2], tmp2[2];
float time1, time2;
CgeVec2fSub(aEnd, aStart, tmp1);
CgeVec2fSub(bEnd, bStart, tmp2);
if (CgeRay2fIntersectTime(aStart, tmp1, bStart, tmp2, &time1, &time2))
return 0;
if (time1 < 0.0f || time1 > 1.0f || time2 < 0.0f || time2 > 1.0f)
return 0;
CgeVec2fLerp(aStart, aEnd, time1, out);
*t = time1;
return 1;
}
int CgeRay2fIntersectBox2f(const float aStart[2], const float aDirection[2],
const float bMin[2], const float bMax[2],
float *t, float out[2]) {
float timeNear, timeFar, hitNear, hitFar, denom, tmp;
int i;
timeNear = -1.0f / 0.0f;
timeFar = 1.0f / 0.0f;
/* Check if origin inside box */
if (!CgeBox2fContains(bMin, bMax, aStart)) {
memcpy(out, aStart, sizeof(float) * 2);
*t = 0.0f;
return 1;
}
/* Check each axis for the minimal and maximum intersection time */
for (i = 0; i < 2; i++) {
if (fabsf(aDirection[i]) < EPSILON) {
if (aStart[i] < bMin[i] || aStart[i] > bMax[i])
return 0;
continue;
}
denom = 1.0f / aDirection[i];
hitNear = (bMin[i] - aStart[i]) * denom;
hitFar = (bMax[i] - aStart[i]) * denom;
if (hitNear > hitFar) {
tmp = hitNear;
hitNear = hitFar;
hitFar = tmp;
}
if (hitNear > timeNear)
timeNear = hitNear;
if (hitFar < timeFar)
timeFar = hitFar;
if (timeNear > timeFar || timeFar < 0.0f)
return 0;
}
out[0] = aStart[0] + aDirection[0] * timeNear;
out[1] = aStart[1] + aDirection[1] * timeNear;
*t = timeNear;
return 1;
}
int CgeSegment2fIntersectBox2f(const float aStart[2], const float aEnd[2],
const float bMin[2], const float bMax[2],
float *t, float out[2]) {
float tmp[3];
float time;
CgeVec2fSub(aEnd, aStart, tmp);
if (CgeRay2fIntersectBox2f(aStart, tmp, bMin, bMax, &time, out))
return 0;
if (time > 1.0f)
return 0;
*t = time;
return 1;
}

195
Ray3f.c Normal file
View File

@@ -0,0 +1,195 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define EPSILON 0.00001f
#define PI 3.14159265358979323846f
int CgeRay3fIntersectPlane(const float start[3], const float direction[3],
const float plane[4], float *t, float out[3]) {
float tmp1[3];
float denom, time;
/* Calculate intersection time */
denom = CgeVec3fDot(direction, plane);
time = (plane[3] - CgeVec3fDot(plane, start)) / denom;
/* Check for ray/plane parallel to each other or point is behing the ray. */
if (fabsf(denom) < EPSILON || time < 0.0f)
return 0;
/* Compute intersection point */
CgeVec3fScale(direction, time, tmp1);
CgeVec3fAdd(start, tmp1, out);
*t = time;
return 1;
}
int CgeRay3fIntersectTriangle(const float start[3], const float direction[3],
const float a[3], const float b[3],
const float c[3], float *t, float out[3]) {
float plane[4];
float tmp1[3], tmp2[3], tmp3[3];
float time;
/* Compute plane */
if (CgePlaneFromPoints(a, b, c, plane))
return 0;
/* Compute intersection point in ray against plane */
if (CgeRay3fIntersectPlane(start, direction, plane, &time, tmp3))
return 0;
/* Check if point inside rectangle */
CgeVec3fSub(b, a, tmp1);
CgeVec3fSub(tmp3, a, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
CgeVec3fSub(c, b, tmp1);
CgeVec3fSub(tmp3, b, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
CgeVec3fSub(a, c, tmp1);
CgeVec3fSub(tmp3, c, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
/* Copy intersection point */
memcpy(out, tmp3, sizeof(tmp3));
*t = time;
return 1;
}
int CgeSegment3fIntersectPlane(const float start[3], const float end[3],
const float plane[4], float *t, float out[3]) {
float tmp[3];
float denom, time;
/* Calculate intersection time */
CgeVec3fSub(end, start, tmp);
denom = CgeVec3fDot(tmp, plane);
time = (plane[3] - CgeVec3fDot(plane, start)) / denom;
/* Check for ray/plane parallel to each other or point is behing the ray. */
if (fabsf(denom) < EPSILON || time < 0.0f || time > 1.0f)
return 0;
/* Compute intersection point */
CgeVec3fScale(tmp, time, tmp);
CgeVec3fAdd(start, tmp, out);
*t = time;
return 1;
}
int CgeSegment3fIntersectTriangle(const float start[3], const float end[3],
const float a[3], const float b[3],
const float c[3], float *t, float out[3]) {
float plane[4];
float tmp1[3], tmp2[3], tmp3[3];
float time;
/* Compute plane */
if (CgePlaneFromPoints(a, b, c, plane))
return 0;
/* Compute intersection point in ray against plane */
if (CgeSegment3fIntersectPlane(start, end, plane, &time, tmp3))
return 0;
/* Check if point inside rectangle */
CgeVec3fSub(b, a, tmp1);
CgeVec3fSub(tmp3, a, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
CgeVec3fSub(c, b, tmp1);
CgeVec3fSub(tmp3, b, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
CgeVec3fSub(a, c, tmp1);
CgeVec3fSub(tmp3, c, tmp2);
CgeVec3fCross(tmp2, tmp1, tmp1);
if (CgeVec3fDot(tmp1, plane) < 0.0f)
return 0;
/* Copy intersection point */
memcpy(out, tmp3, sizeof(tmp3));
*t = time;
return 1;
}
int CgeRay3fIntersectBox3f(const float aStart[3], const float aDirection[3],
const float bMin[3], const float bMax[3], float *t,
float out[3]) {
float timeNear, timeFar, hitNear, hitFar, denom, tmp;
int i;
timeNear = -1.0f / 0.0f;
timeFar = 1.0f / 0.0f;
/* Check if origin inside box */
if (!CgeBox3fContains(bMin, bMax, aStart)) {
memcpy(out, aStart, sizeof(float) * 3);
*t = 0.0f;
return 1;
}
/* Check each axis for the minimal and maximum intersection time */
for (i = 0; i < 3; i++) {
if (fabsf(aDirection[i]) < EPSILON) {
if (aStart[i] < bMin[i] || aStart[i] > bMax[i])
return 0;
continue;
}
denom = 1.0f / aDirection[i];
hitNear = (bMin[i] - aStart[i]) * denom;
hitFar = (bMax[i] - aStart[i]) * denom;
if (hitNear > hitFar) {
tmp = hitNear;
hitNear = hitFar;
hitFar = tmp;
}
if (hitNear > timeNear)
timeNear = hitNear;
if (hitFar < timeFar)
timeFar = hitFar;
if (timeNear > timeFar || timeFar < 0.0f)
return 0;
}
out[0] = aStart[0] + aDirection[0] * timeNear;
out[1] = aStart[1] + aDirection[1] * timeNear;
out[2] = aStart[2] + aDirection[2] * timeNear;
*t = timeNear;
return 1;
}
int CgeSegment3fIntersectBox3f(const float aStart[3], const float aEnd[3],
const float bMin[3], const float bMax[3],
float *t, float out[3]) {
float tmp[3];
float time;
CgeVec3fSub(aEnd, aStart, tmp);
if (CgeRay3fIntersectBox3f(aStart, tmp, bMin, bMax, &time, out))
return 0;
if (time > 1.0f)
return 0;
*t = time;
return 1;
}

95
Vec2f.c Normal file
View File

@@ -0,0 +1,95 @@
#include "CgeMath.h"
#include <math.h>
#define SET_ROW(row, val) row[0] = row[1] = val
void CgeVec2fAdd(const float a[2], const float b[2], float out[2]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
}
void CgeVec2fSub(const float a[2], const float b[2], float out[2]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
}
void CgeVec2fMul(const float a[2], const float b[2], float out[2]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
}
void CgeVec2fScale(const float a[2], float b, float out[2]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
}
void CgeVec2fMulAdd(const float a[2], const float b[2], const float c[2],
float out[2]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
}
void CgeVec2fNegate(const float in[2], float out[2]) {
out[0] = -in[0];
out[1] = -in[1];
}
float CgeVec2fDot(const float a[2], const float b[2]) {
return a[0] * b[0] + a[1] * b[1];
}
float CgeVec2fCross(const float a[2], const float b[2]) {
return a[0] * b[1] - a[1] * b[0];
}
float CgeVec2fLength(const float in[2]) {
return sqrtf(CgeVec2fDot(in, in));
}
void CgeVec2fNormal(const float in[2], float out[2]) {
CgeVec2fScale(in, 1.0f / CgeVec2fLength(in), out);
}
float CgeVec2fNormalEx(const float in[2], float out[2]) {
float length;
length = CgeVec2fLength(in);
CgeVec2fScale(in, 1.0f / length, out);
return length;
}
void CgeVec2fMin(const float a[2], const float b[2], float out[2]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
}
void CgeVec2fMax(const float a[2], const float b[2], float out[2]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
}
void CgeVec2fLerp(const float a[2], const float b[2], float t, float out[2]) {
float tmp[2];
CgeVec2fSub(b, a, tmp);
CgeVec2fScale(tmp, t, tmp);
CgeVec2fAdd(a, tmp, out);
}
void CgeVec2fProject(const float a[2], const float b[2], float out[2]) {
float amount;
amount = CgeVec2fDot(a, b) / CgeVec2fDot(b, b);
CgeVec2fScale(b, amount, out);
}
void CgeVec2fBarycentric(const float a[2], const float b[2], const float c[2],
float v, float w, float out[2]) {
float tmp1[2], tmp2[2];
float u;
u = 1.0f - v - w;
SET_ROW(tmp1, u); CgeVec2fMul(a, tmp1, tmp2);
SET_ROW(tmp1, v); CgeVec2fMulAdd(b, tmp1, tmp2, tmp2);
SET_ROW(tmp1, w); CgeVec2fMulAdd(c, tmp1, tmp2, out);
}

42
Vec2i.c Normal file
View File

@@ -0,0 +1,42 @@
#include "CgeMath.h"
void CgeVec2iAdd(const int a[2], const int b[2], int out[2]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
}
void CgeVec2iSub(const int a[2], const int b[2], int out[2]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
}
void CgeVec2iMul(const int a[2], const int b[2], int out[2]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
}
void CgeVec2iScale(const int a[2], int b, int out[2]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
}
void CgeVec2iMulAdd(const int a[2], const int b[2], const int c[2],
int out[2]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
}
void CgeVec2iNegate(const int in[2], int out[2]) {
out[0] = -in[0];
out[1] = -in[1];
}
void CgeVec2iMin(const int a[2], const int b[2], int out[2]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
}
void CgeVec2iMax(const int a[2], const int b[2], int out[2]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
}

109
Vec3f.c Normal file
View File

@@ -0,0 +1,109 @@
#include "CgeMath.h"
#include <string.h>
#include <math.h>
#define SET_ROW(row, val) row[0] = row[1] = row[2] = val
void CgeVec3fAdd(const float a[3], const float b[3], float out[3]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
}
void CgeVec3fSub(const float a[3], const float b[3], float out[3]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
}
void CgeVec3fMul(const float a[3], const float b[3], float out[3]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
}
void CgeVec3fScale(const float a[3], float b, float out[3]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
}
void CgeVec3fMulAdd(const float a[3], const float b[3], const float c[3],
float out[3]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
out[2] = a[2] * b[2] + c[2];
}
void CgeVec3fNegate(const float in[3], float out[3]) {
out[0] = -in[0];
out[1] = -in[1];
out[2] = -in[2];
}
float CgeVec3fDot(const float a[3], const float b[3]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
void CgeVec3fCross(const float a[3], const float b[3], float out[3]) {
float tmp[3];
tmp[0] = a[1] * b[2] - a[2] * b[1];
tmp[1] = a[2] * b[0] - a[0] * b[2];
tmp[2] = a[0] * b[1] - a[1] * b[0];
memcpy(out, tmp, sizeof(tmp));
}
float CgeVec3fLength(const float in[3]) {
return sqrtf(CgeVec3fDot(in, in));
}
void CgeVec3fNormal(const float in[3], float out[3]) {
CgeVec3fScale(in, 1.0f / CgeVec3fLength(in), out);
}
float CgeVec3fNormalEx(const float in[3], float out[3]) {
float length;
length = CgeVec3fLength(in);
CgeVec3fScale(in, 1.0f / length, out);
return length;
}
void CgeVec3fMin(const float a[3], const float b[3], float out[3]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2];
}
void CgeVec3fMax(const float a[3], const float b[3], float out[3]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2];
}
void CgeVec3fLerp(const float a[3], const float b[3], float t, float out[3]) {
float tmp[3];
CgeVec3fSub(b, a, tmp);
CgeVec3fScale(tmp, t, tmp);
CgeVec3fAdd(a, tmp, out);
}
void CgeVec3fProject(const float a[3], const float b[3], float out[3]) {
float amount;
amount = CgeVec3fDot(a, b) / CgeVec3fDot(b, b);
CgeVec3fScale(b, amount, out);
}
void CgeVec3fBarycentric(const float a[3], const float b[3], const float c[3],
float v, float w, float out[3]) {
float tmp1[3], tmp2[3];
float u;
u = 1.0f - v - w;
SET_ROW(tmp1, u); CgeVec3fMul(a, tmp1, tmp2);
SET_ROW(tmp1, v); CgeVec3fMulAdd(b, tmp1, tmp2, tmp2);
SET_ROW(tmp1, w); CgeVec3fMulAdd(c, tmp1, tmp2, out);
}

50
Vec3i.c Normal file
View File

@@ -0,0 +1,50 @@
#include "CgeMath.h"
void CgeVec3iAdd(const int a[3], const int b[3], int out[3]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
}
void CgeVec3iSub(const int a[3], const int b[3], int out[3]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
}
void CgeVec3iMul(const int a[3], const int b[3], int out[3]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
}
void CgeVec3iScale(const int a[3], int b, int out[3]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
}
void CgeVec3iMulAdd(const int a[3], const int b[3], const int c[3],
int out[3]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
out[2] = a[2] * b[2] + c[2];
}
void CgeVec3iNegate(const int in[3], int out[3]) {
out[0] = -in[0];
out[1] = -in[1];
out[2] = -in[2];
}
void CgeVec3iMin(const int a[3], const int b[3], int out[3]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2];
}
void CgeVec3iMax(const int a[3], const int b[3], int out[3]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2];
}

108
Vec4f.c Normal file
View File

@@ -0,0 +1,108 @@
#include "CgeMath.h"
#include <math.h>
#define SET_ROW(row, val) row[0] = row[1] = row[2] = row[3] = val
void CgeVec4fAdd(const float a[4], const float b[4], float out[4]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
}
void CgeVec4fSub(const float a[4], const float b[4], float out[4]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
}
void CgeVec4fMul(const float a[4], const float b[4], float out[4]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
out[3] = a[3] * b[3];
}
void CgeVec4fScale(const float a[4], float b, float out[4]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
}
void CgeVec4fMulAdd(const float a[4], const float b[4], const float c[4],
float out[4]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
out[2] = a[2] * b[2] + c[2];
out[3] = a[3] * b[3] + c[3];
}
void CgeVec4fNegate(const float in[4], float out[4]) {
out[0] = -in[0];
out[1] = -in[1];
out[2] = -in[2];
out[3] = -in[3];
}
float CgeVec4fDot(const float a[4], const float b[4]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
float CgeVec4fLength(const float in[4]) {
return sqrtf(CgeVec4fDot(in, in));
}
void CgeVec4fNormal(const float in[4],
float out[4]) {
CgeVec4fScale(in, 1.0f / CgeVec4fLength(in), out);
}
float CgeVec4fNormalEx(const float in[4], float out[4]) {
float length;
length = CgeVec4fLength(in);
CgeVec4fScale(in, 1.0f / length, out);
return length;
}
void CgeVec4fMin(const float a[4], const float b[4], float out[4]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2];
if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3];
}
void CgeVec4fMax(const float a[4], const float b[4], float out[4]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2];
if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3];
}
void CgeVec4fLerp(const float a[4], const float b[4], float t, float out[4]) {
float tmp[4];
CgeVec4fSub(b, a, tmp);
CgeVec4fScale(tmp, t, tmp);
CgeVec4fAdd(a, tmp, out);
}
void CgeVec4fProject(const float a[4], const float b[4], float out[4]) {
float amount;
amount = CgeVec4fDot(a, b) / CgeVec4fDot(b, b);
CgeVec4fScale(b, amount, out);
}
void CgeVec4fBarycentric(const float a[4], const float b[4], const float c[4],
float v, float w, float out[4]) {
float tmp1[4], tmp2[4];
float u;
u = 1.0f - v - w;
SET_ROW(tmp1, u); CgeVec4fMul(a, tmp1, tmp2);
SET_ROW(tmp1, v); CgeVec4fMulAdd(b, tmp1, tmp2, tmp2);
SET_ROW(tmp1, w); CgeVec4fMulAdd(c, tmp1, tmp2, out);
}

58
Vec4i.c Normal file
View File

@@ -0,0 +1,58 @@
#include "CgeMath.h"
void CgeVec4iAdd(const int a[4], const int b[4], int out[4]) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
}
void CgeVec4iSub(const int a[4], const int b[4], int out[4]) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
}
void CgeVec4iMul(const int a[4], const int b[4], int out[4]) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
out[3] = a[3] * b[3];
}
void CgeVec4iScale(const int a[4], int b, int out[4]) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
}
void CgeVec4iMulAdd(const int a[4], const int b[4], const int c[4],
int out[4]) {
out[0] = a[0] * b[0] + c[0];
out[1] = a[1] * b[1] + c[1];
out[2] = a[2] * b[2] + c[2];
out[3] = a[3] * b[3] + c[3];
}
void CgeVec4iNegate(const int in[4], int out[4]) {
out[0] = -in[0];
out[1] = -in[1];
out[2] = -in[2];
out[3] = -in[3];
}
void CgeVec4iMin(const int a[4], const int b[4], int out[4]) {
if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2];
if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3];
}
void CgeVec4iMax(const int a[4], const int b[4], int out[4]) {
if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0];
if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1];
if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2];
if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3];
}