all repos — engine.git @ 70d5a5f53436c4848616132f2ff47c4036adc224

Unnamed repository; edit this file 'description' to name the repository.

src/common/math.odin

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
package common

import "core:fmt"
import "core:math"

FRAC_BITS : u64 : 31
FRAC_BIT_MASK : iFP : 0x7FFFFFFF
INT_BITS : u64 : 32
FP_ONE :: f32(1 << FRAC_BITS)
DB_ONE :: f64(1 << FRAC_BITS)
TOLERENCE : iFP : 21474
METER : iFP : 2147483648
TWO_METER : iFP : 4294967296
FOUR_METER : iFP : 8589934592
INF : iFP : 0x7FFFFFFFFFFFFFFF
SQRT2 : iFP : 3037000448

BOX_NORMALS := [6][3]iFP {
	[3]iFP{METER,0,0},
	[3]iFP{-METER,0,0},
	[3]iFP{0,METER,0},
	[3]iFP{0,-METER,0},
	[3]iFP{0,0,METER},
	[3]iFP{0,0,-METER},
}


iFP :: distinct i64

Plane :: struct {
	normal: [3]iFP,
	center: [3]iFP,
}

PlaneSide :: enum {
	OUTSIDE,
	INSIDE
}


FloatToInt :: proc(f: f32) -> iFP {
	intComponent := iFP(f)
	fracComponent := f-f32(intComponent)
	result := intComponent << FRAC_BITS
	result += iFP(fracComponent * FP_ONE)
	return result
}

DoubleToInt :: proc(f: f64) -> iFP {
	intComponent := iFP(f)
	fracComponent := f-f64(intComponent)
	result := intComponent << FRAC_BITS
	result += iFP(fracComponent * DB_ONE)
	return result
}

IntToFloat :: proc(i: iFP) -> f32 {
	intPart := f32(i >> FRAC_BITS)
	fracPart := f32(i & FRAC_BIT_MASK)/FP_ONE
	return intPart+fracPart
}

ToFloatVector :: proc(vec: [3]iFP) -> [3]f32 {
	vecFloat :[3]f32
	for x,i in vec do vecFloat[i] = IntToFloat(x)
	return vecFloat
}

ToIntVector :: proc(vec: [3]f32) -> [3]iFP {
	vecInt : [3]iFP
	for x,i in vec do vecInt[i] = FloatToInt(x)
	return vecInt
}

Mul :: proc(i1: iFP, i2: iFP) -> iFP {
	intPart1 := i1 >> FRAC_BITS
	intPart2 := i2 >> FRAC_BITS

	fracPart1 := i1 & FRAC_BIT_MASK 
	fracPart2 := i2 & FRAC_BIT_MASK

	result: iFP = 0
	result += (intPart1*intPart2) << FRAC_BITS
	result += (intPart1*fracPart2)
	result += (fracPart1*intPart2)
	result += ((fracPart1*fracPart2) >> FRAC_BITS) & FRAC_BIT_MASK

	return result
}

Div :: proc(n: iFP, d: iFP) -> iFP {
	one := iFP(1 << (FRAC_BITS+INT_BITS-1))
	reciprocal: iFP = (one/d) 	
	return Mul(n,reciprocal)
}

VecMul :: proc(vec: [3]iFP, sc: iFP) -> [3]iFP {
	vecNew : [3]iFP
	for x,i in vec do vecNew[i] = Mul(x,sc)
	return vecNew
}

VecDiv :: proc(vec: [3]iFP, sc: iFP) -> [3]iFP {
	vecNew : [3]iFP
	for x,i in vec do vecNew[i] = Div(x,sc)
	return vecNew
}

InvSqrt :: proc(x: iFP) -> iFP {
	xf :f32 = IntToFloat(x)
	if xf <= 0.0 do return 0
	yf :f32 = 1.0 / math.sqrt(xf)

	y0 := FloatToInt(yf)
	y1 := Div((Mul(x,Mul(y0,Mul(y0,y0))) + y0),FloatToInt(2.0))

	for math.abs(y1-y0) > TOLERENCE {
		y0 = y1
		y1 = Div((Mul(x,Mul(y0,Mul(y0,y0))) - y0),FloatToInt(2.0))
	}

	return y1
}

CrossProduct :: proc(v1: [3]iFP, v2: [3]iFP) -> [3]iFP {
	return [3]iFP{
		Mul(v1[1],v2[2]) - Mul(v1[2],v2[1]),
		Mul(v1[2],v2[0]) - Mul(v1[0],v2[2]),
		Mul(v1[0],v2[1]) - Mul(v1[1],v2[0]),
	}
}

DotProduct :: proc(v1: [3]iFP, v2: [3]iFP) -> iFP {
	return Mul(v1[0],v2[0])+Mul(v1[1],v2[1])+Mul(v1[2],v2[2])
}

Normalize :: proc(vec: [3]iFP) -> [3]iFP {
	return VecMul(vec,InvSqrt(DotProduct(vec,vec)))
}

PointInsidePlane :: proc(point: [3]iFP, plane: Plane) -> PlaneSide {
	if DotProduct(point-plane.center,plane.normal) > 0 do return PlaneSide.OUTSIDE
	else do return PlaneSide.INSIDE
}

LinePlaneIntersection :: proc(origin: [3]iFP, target: [3]iFP, plane: Plane) -> ([3]iFP, bool) {
	denom: iFP = DotProduct(Normalize(target-origin),plane.normal)
	if denom == 0 {
		return origin, false
	}
	return VecMul(Normalize(target-origin),Div(DotProduct(plane.center-origin,plane.normal),denom)) + origin, true
}