init dump

This commit is contained in:
2024-05-05 17:01:56 +10:00
commit 608cf45822
53 changed files with 19224 additions and 0 deletions

View File

@ -0,0 +1,276 @@
import Foundation
import simd
import JolkEngine
@main struct Program
{
static func main()
{
Application(
application: CavesOfJolk(),
config: ApplicationConfiguration(
resizable: true,
vSync: .on,
windowWidth: 1280,
windowHeight: 720,
bundle: Bundle.module)
).run()
}
}
class CavesOfJolk: ApplicationImplementation
{
private var aspect: Float = 0
private var drawEdges = false
var env = Environment()
var worldMesh = RenderMesh.empty, cube = RenderMesh.empty, suzanne = RenderMesh.empty, toybox = RenderMesh.empty
var texture = Texture2D.empty, jolkTex = Texture2D.empty, suzanneDiffuse = Texture2D.empty
private lazy var world = Collision()
private lazy var colin = Colin()
private lazy var jolkCube = JolkCube(position: .init(0, 1, -4))
private var lightTheta: Float = 0
private var frameCount = 0
private var frameTimer: Float = 1
func create(render: inout Renderer)
{
render.clearColour = XnaColour.CornflowerBlue
env.setFog(
colour: XnaColour.CornflowerBlue,
//mode: .depth, falloff: .range(type: .linear, start: 4, end: 38))
//mode: .depth, falloff: .range(type: .linear, start: 1.25, end: 24.5))
//mode: .distance, falloff: .factor(type: .exp2, density: 0.1))
mode: .depth, falloff: .factor(type: .exp2, density: 0.0222))
env.addAmbientLight(colour: XnaColour.DarkSlateGray.lighten(by: -0.666))
env.addDirectionalLight(
direction: -Vec3f(1, -1, -1).normalised,
colour: XnaColour.BlanchedAlmond
.lighten(by: -0.02)
.mix(with: XnaColour.LightSlateGray, 0.5)
.mix(with: XnaColour.White, 0.125))
env.addPointLight(
position: Vec3f(3, 0.33, -5),
colour: XnaColour.Green.mix(with: XnaColour.Gray, 0.5),
intensity: 2)
env.addPointLight(
position: Vec3f(5.5, 0.33, -6),
colour: XnaColour.Red.mix(with: XnaColour.Gray, 0.5),
intensity: 2)
env.addPointLight(
position: Vec3f(4, 0.33, -7),
colour: XnaColour.Blue.mix(with: XnaColour.Gray, 0.5),
intensity: 2)
}
func loadContent(content: inout ContentManager) throws
{
try loadWorld(&content)
cube = try content.create(mesh: .init(
vertices: [
.init(position: Vec3f(-1, -1, 1), normal: .forward, texCoord: Vec2f(0, 0)),
.init(position: Vec3f( 1, -1, 1), normal: .forward, texCoord: Vec2f(1, 0)),
.init(position: Vec3f(-1, 1, 1), normal: .forward, texCoord: Vec2f(0, 1)),
.init(position: Vec3f( 1, 1, 1), normal: .forward, texCoord: Vec2f(1, 1)),
.init(position: Vec3f( 1, -1, 1), normal: .right, texCoord: Vec2f(0, 0)),
.init(position: Vec3f( 1, -1, -1), normal: .right, texCoord: Vec2f(1, 0)),
.init(position: Vec3f( 1, 1, 1), normal: .right, texCoord: Vec2f(0, 1)),
.init(position: Vec3f( 1, 1, -1), normal: .right, texCoord: Vec2f(1, 1)),
.init(position: Vec3f( 1, -1, -1), normal: .back, texCoord: Vec2f(0, 0)),
.init(position: Vec3f(-1, -1, -1), normal: .back, texCoord: Vec2f(1, 0)),
.init(position: Vec3f( 1, 1, -1), normal: .back, texCoord: Vec2f(0, 1)),
.init(position: Vec3f(-1, 1, -1), normal: .back, texCoord: Vec2f(1, 1)),
.init(position: Vec3f(-1, -1, -1), normal: .left, texCoord: Vec2f(0, 0)),
.init(position: Vec3f(-1, -1, 1), normal: .left, texCoord: Vec2f(1, 0)),
.init(position: Vec3f(-1, 1, -1), normal: .left, texCoord: Vec2f(0, 1)),
.init(position: Vec3f(-1, 1, 1), normal: .left, texCoord: Vec2f(1, 1)),
.init(position: Vec3f(-1, -1, -1), normal: .down, texCoord: Vec2f(0, 0)),
.init(position: Vec3f( 1, -1, -1), normal: .down, texCoord: Vec2f(1, 0)),
.init(position: Vec3f(-1, -1, 1), normal: .down, texCoord: Vec2f(0, 1)),
.init(position: Vec3f( 1, -1, 1), normal: .down, texCoord: Vec2f(1, 1)),
.init(position: Vec3f(-1, 1, 1), normal: .up, texCoord: Vec2f(0, 0)),
.init(position: Vec3f( 1, 1, 1), normal: .up, texCoord: Vec2f(1, 0)),
.init(position: Vec3f(-1, 1, -1), normal: .up, texCoord: Vec2f(0, 1)),
.init(position: Vec3f( 1, 1, -1), normal: .up, texCoord: Vec2f(1, 1))
],
indices: [
0, 1, 2, 2, 1, 3,
4, 5, 6, 6, 5, 7,
8, 9, 10, 10, 9, 11,
12, 13, 14, 14, 13, 15,
16, 17, 18, 18, 17, 19,
20, 21, 22, 22, 21, 23 ]))
suzanne = try content.load("suzanne.g3db")
toybox = try content.load("toybox.g3db")
let linearMipped = Texture2DParameters(
minFilter: .linear, magFilter: .linear,
wrapMode: .repeating,
mipMode: .linear)
let linearClamp = Texture2DParameters(
minFilter: .linear, magFilter: .linear,
wrapMode: .clampEdge)
texture = try content.load("cobblestone.png", params: linearMipped)
jolkTex = try content.load("jolkmeup.jpg", params: linearClamp)
suzanneDiffuse = try content.load("suzanne_diffuse.png", params: linearMipped)
}
func resize(width: Int, height: Int)
{
aspect = Float(width) / Float(height)
print(aspect)
}
func update(deltaTime: Float)
{
colin.update(deltaTime: deltaTime, world: world)
jolkCube.update(deltaTime: deltaTime, world: world)
lightTheta += deltaTime
frameCount += 1
frameTimer -= deltaTime
if frameTimer <= 0
{
print("FPS: \(frameCount)")
frameCount = 0
frameTimer += 1.0
}
}
private func loadWorld(_ content: inout ContentManager) throws
{
//let world: Mesh = try content.load("World.obj")
let obj = try ObjReader.read(url: try content.getResource("World.obj"))
let mesh: Mesh = try ObjLoader.read(model: obj)
worldMesh = try content.create(mesh: mesh)
if let collision = obj.objects["Collision3D"]
{
world.build(obj: obj, collision: collision)
}
}
/*
if let collision = world.subMeshes["Collision"]
{
edges.reserveCapacity(collision.length / 6)
let get2dVertex =
{ i in
let vertex = world.vertices[Int(world.indices[i])]
let position = Vec2f(vertex.position.x, vertex.position.z)
let normal = Vec2f(vertex.normal.x, vertex.normal.z)
return (position, normal)
}
for i in stride(from: collision.start, to: collision.start + collision.length, by: 3)
{
let (v0p, v0n) = get2dVertex(i)
let (v1p, v1n) = get2dVertex(i + 1)
let (v2p, v2n) = get2dVertex(i + 2)
let (p0, p1) = if v0p == v2p || v1p == v2p { (v0p, v1p) }
else if v0p == v1p { (v0p, v2p) }
else { throw NSError() }
let edge = Edge(p: p0.lerp(p1, 0.5), n: (v0n + v1n + v2n).normalised, w: (p0 - p1).len)
if !edges.contains(where: { edge.p == $0.p && edge.w == $0.w })
{
edges.append(edge)
}
}
}
*/
func draw(render: inout Renderer, deltaTime: Float)
{
// Setup camera
render.setProjection(matrix:
.perspective(fovY: Float.rad(fromDeg: colin.fov), aspect: aspect, zNear: 0.1, zFar: 100))
render.setView(matrix: colin.transform)
// Update point lights
var theta = Vec3f(repeating: lightTheta) * Vec3f(0.12, 0.011, 0.056) * 6
var i = env.lights.startIndex
while i != env.lights.endIndex
{
if case .point(let colour, _, _) = env.lights[i]
{
env.lights[i] = .point(
colour: colour,
position: Vec3f(
4 + 6 * cos(theta[0]),
0.33 + 0.33 * sin(theta[1]),
-6 + 3 * sin(theta[0] * 2)),
intensity: 3.1 + 1.53 * cos(theta[2]))
let spacing = 0.5 * Float.pi * (2 / 3.0)
theta += spacing * Vec3f(1, 0.98, 0.5566)
}
i = env.lights.index(after: i)
}
// Draw world
render.setMaterial(Material(
specular: XnaColour.BlanchedAlmond.mix(with: .black, 0.12),
texture: texture.id))
render.draw(mesh: worldMesh, environment: env)
// Draw jolked up shit
render.setMaterial(Material(
specular: XnaColour.Gray,
gloss: 20.0,
texture: jolkTex.id))
render.draw(mesh: cube, model: jolkCube.transform, environment: env)
render.setMaterial(Material(texture: suzanneDiffuse.id))
render.draw(mesh: suzanne, model: .translate(.up + Vec3f(3.0, 0.0, -3.5) * 2.5), environment: env)
render.draw(mesh: toybox,
model: .translate(Vec3f(6.0, 0.667, -3.5) * Vec3f(2.5, 1, 2.5))
* .rotate(y: lightTheta * 0.5) * .scale(scalar: 0.25), environment: env)
if Input.instance.keyPressed(.c) { drawEdges = !drawEdges }
if drawEdges
{
/*
var lines = [Line](
repeating: .init(from: .init(), to: .init(), colour: .zero),
count: edges.count * 3)
var i: Int = 0
for edge in edges
{
let tangent = Vec2f(edge.n.y, -edge.n.x)
let a = edge.p - tangent * edge.w * 0.5
let b = edge.p + tangent * edge.w * 0.5
lines[i] = Line(
from: Vec3f(a.x, 0, a.y),
to: Vec3f(b.x, 0, b.y),
colour: Colour(r: 0.1, g: 0.9, b: 0.1))
lines[i + 1] = Line(
from: Vec3f(edge.p.x, 0, edge.p.y),
to: Vec3f(edge.p.x + edge.n.x * 0.25, 0, edge.p.y + edge.n.y * 0.25),
colour: Colour(r: 0.9, g: 0.1, b: 0.1))
let deltaPos = Vec2f(colin.position.x, colin.position.z) - edge.p
let something = tangent * deltaPos.cross(edge.n)
lines[i + 2] = Line(
from: Vec3f(edge.p.x + something.x, 0.0, edge.p.y + something.y),
to: Vec3f(edge.p.x + something.x + edge.n.x * 0.5, 0.0, edge.p.y + something.y + edge.n.y * 0.5),
colour: XnaColour.Azure)
i += 3
}
render.drawGizmos(lines: lines)
*/
world.draw(render, position: colin.position)
}
}
}

View File

@ -0,0 +1,497 @@
import Foundation
import JolkEngine
class Collision
{
struct Edge { let p: Vec2f, n: Vec2f, w: Float }
enum Edge3D
{
case triangle(n: Vec3f, p: Vec3f, v: (Vec3f, Vec3f, Vec3f))
case aabbFloor(n: Vec3f, p: Vec3f, w: Float, d: Float)
case quad(p: (Vec3f, Vec3f, Vec3f, Vec3f), w: Winding)
}
var edge3d = [Edge3D]()
/*
0,-2 1,-2
*--*
| |
0,-1 * * 1,-1
| |
*--*
0, 0 1, 0
*/
init()
{
assert(Self.isRectangle([
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
]))
// CW
assert(Self.isRectangle([
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
Vec3f(0.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
]))
assert(Self.isRectangle([
Vec3f(0.0, 0.0, -1.0),
Vec3f(0.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
Vec3f(0.0, 0.0, 0.0),
]))
assert(Self.isRectangle([
Vec3f(0.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
]))
assert(Self.isRectangle([
Vec3f(1.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
Vec3f(0.0, 0.0, -2.0),
]))
assert(Self.isRectangle([
Vec3f(1.0, 0.0, -1.0),
Vec3f(1.0, 0.0, 0.0),
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
Vec3f(0.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -2.0),
]))
assert(Self.isRectangle([
Vec3f(1.0, 0.0, 0.0),
Vec3f(0.0, 0.0, 0.0),
Vec3f(0.0, 0.0, -1.0),
Vec3f(0.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -2.0),
Vec3f(1.0, 0.0, -1.0),
]))
// CCW
assert(Self.isRectangle([
Vec3f( 0.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, -1.0),
Vec3f( 0.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -1.0),
Vec3f(-1.0, 0.0, 0.0),
]))
assert(Self.isRectangle([
Vec3f( 0.0, 0.0, -1.0),
Vec3f( 0.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -1.0),
Vec3f(-1.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, 0.0),
]))
assert(Self.isRectangle([
Vec3f( 0.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -1.0),
Vec3f(-1.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, -1.0),
]))
assert(Self.isRectangle([
Vec3f(-1.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -1.0),
Vec3f(-1.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, -1.0),
Vec3f( 0.0, 0.0, -2.0),
]))
assert(Self.isRectangle([
Vec3f(-1.0, 0.0, -1.0),
Vec3f(-1.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, -1.0),
Vec3f( 0.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -2.0),
]))
assert(Self.isRectangle([
Vec3f(-1.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, 0.0),
Vec3f( 0.0, 0.0, -1.0),
Vec3f( 0.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -2.0),
Vec3f(-1.0, 0.0, -1.0),
]))
}
private static let epsilon: Float = 0.00001 //.ulpOfOne
private static func isSimpleQuad(_ p: (Vec3f, Vec3f, Vec3f, Vec3f)) -> Bool
{
if abs(p.0.y - p.1.y) <= epsilon { return abs(p.2.y - p.3.y) <= epsilon }
if abs(p.1.y - p.2.y) <= epsilon { return abs(p.3.y - p.0.y) <= epsilon }
return false
}
private static func isRectangle(_ p: (Vec3f, Vec3f, Vec3f, Vec3f)) -> Bool
{
if abs(p.0.x - p.1.x) <= epsilon &&
abs(p.1.z - p.2.z) <= epsilon &&
abs(p.2.x - p.3.x) <= epsilon &&
abs(p.3.z - p.0.z) <= epsilon { return true }
if abs(p.0.z - p.1.z) <= epsilon &&
abs(p.1.x - p.2.x) <= epsilon &&
abs(p.2.z - p.3.z) <= epsilon &&
abs(p.3.x - p.0.x) <= epsilon { return true }
return false
}
private static func isRectangle(_ positions: [Vec3f]) -> Bool
{
var winding: Winding = .none
var xdir: Float = 0.0, zdir: Float = 0.0
let first = positions[0]
var previous = first
for p in positions[1...]
{
let (xdelta, zdelta) = (p.x - previous.x, p.z - previous.z)
let (xzero, zzero) = (abs(xdelta) <= epsilon, abs(zdelta) <= epsilon)
if !xzero && zzero
{
if xdir != 0.0 && xdelta.sign != xdir.sign { return false }
if zdir != 0.0
{
switch winding
{
case .none: winding = xdelta.sign == zdir.sign ? .ccw : .cw
case .cw: if xdelta.sign == zdir.sign { return false }
case .ccw: if xdelta.sign != zdir.sign { return false }
}
}
(xdir, zdir) = (xdelta, 0.0)
}
else if xzero && !zzero
{
if zdir != 0.0 && zdelta.sign != zdir.sign { return false }
if xdir != 0.0
{
switch winding
{
case .none: winding = zdelta.sign == xdir.sign ? .cw : .ccw
case .cw: if zdelta.sign != xdir.sign { return false }
case .ccw: if zdelta.sign == xdir.sign { return false }
}
}
(xdir, zdir) = (0.0, zdelta)
}
else if !xzero && !zzero { return false }
previous = p
}
return abs(first.x - previous.x) <= epsilon || abs(first.z - previous.z) <= epsilon
}
private static func getQuadWinding(_ p: (Vec3f, Vec3f, Vec3f, Vec3f)) -> Winding
{
var area: Float = 0.0
area += (p.1.x - p.0.x) * ((p.0.z + p.1.z) * 0.5)
area += (p.2.x - p.1.x) * ((p.1.z + p.2.z) * 0.5)
area += (p.3.x - p.2.x) * ((p.2.z + p.3.z) * 0.5)
area += (p.0.x - p.3.x) * ((p.3.z + p.0.z) * 0.5)
return area.sign == .plus ? .ccw : .cw // z is towards us
}
static func quadSpaceFromCartesian(quad: (Vec3f, Vec3f, Vec3f, Vec3f), position: Vec3f) -> Vec2f
{
let p = (
Vec2d(Double(quad.0.x), Double(quad.0.z)),
Vec2d(Double(quad.1.x), Double(quad.1.z)),
Vec2d(Double(quad.2.x), Double(quad.2.z)),
Vec2d(Double(quad.3.x), Double(quad.3.z)))
let xz = Vec2d(Double(position.x), Double(position.z))
/*
let old = {
let a = xz.x - p.0.x
let b = p.1.x - p.0.x
let c = p.3.x - p.0.x
let d = p.0.x - p.1.x + p.2.x - p.3.x
let f = xz.y - p.0.y
let g = p.1.y - p.0.y
let h = p.3.y - p.0.y
let j = p.0.y - p.1.y + p.2.y - p.3.y
let v2 = -c * j - (-d * h)
let v1 = a * j - c * g - (d * f - b * h)
let v0 = a * g - b * f
let vq = (-v1 + sqrt(v1 * v1 - 4.0 * v2 * v0)) / (2.0 * v2)
let uq = (a - c * vq) / (b + d * vq)
return Vec2f(Float(uq), Float(vq))
}
*/
let a = xz - p.0
let b = p.1 - p.0
let c = p.3 - p.0
let d = p.0 - p.1 + p.2 - p.3
let v0 = a.cross(b), v2 = c.cross(-d)
let v1 = a.x * d.y - b.y * c.x - (a.y * d.x - b.x * c.y)
let vq = (-v1 + sqrt(v1 * v1 - 4.0 * v2 * v0)) / (2.0 * v2)
let uq = (a.x - c.x * vq) / (b.x + d.x * vq)
return Vec2f(Float(uq), Float(vq))
//let oldUv = old()
//if !oldUv.x.isNaN || !uv.x.isNaN { assert (oldUv.x == uv.x) }
//if !oldUv.y.isNaN || !uv.y.isNaN { assert (oldUv.y == uv.y) }
//return uv
}
enum Winding { case none, cw, ccw }
func build(obj: ObjModel, collision: ObjModel.Object)
{
for face in collision.faces
{
switch face
{
case .triangle(let v1, let v2, let v3):
let p = (obj.positions[v1.p], obj.positions[v2.p], obj.positions[v3.p])
let n = (obj.normals[v1.n] + obj.normals[v2.n] + obj.normals[v3.n]).normalised
if abs(n.y) < 0.25 { continue }
edge3d.append(.triangle(n: n, p: (p.0 + p.1 + p.2) / 3.0, v: p))
case .quad(let v1, let v2, let v3, let v4):
let p = (obj.positions[v1.p], obj.positions[v2.p], obj.positions[v3.p], obj.positions[v4.p])
let n = (obj.normals[v1.n] + obj.normals[v2.n] + obj.normals[v3.n] + obj.normals[v4.n]).normalised
if Self.isSimpleQuad(p) && Self.isRectangle(p)
{
if abs(n.y) < 0.25 { continue }
let left = min(p.0.x, p.1.x, p.2.x, p.3.x)
let right = max(p.0.x, p.1.x, p.2.x, p.3.x)
let back = min(p.0.z, p.1.z, p.2.z, p.3.z)
let forward = max(p.0.z, p.1.z, p.2.z, p.3.z)
edge3d.append(.aabbFloor(n: n,
p: (p.0 + p.1 + p.2 + p.3) / 4.0,
w: (right - left) / 2.0,
d: (forward - back) / 2.0))
}
else
{
if abs(n.y) < 0.25 { continue }
edge3d.append(.quad(p: p, w: Self.getQuadWinding(p)))
/*
edge3d.append(.triangle(n: n, p: (p.0 + p.1 + p.2) / 3.0, v: (p.0, p.1, p.2)))
edge3d.append(.triangle(n: n, p: (p.2 + p.3 + p.0) / 3.0, v: (p.2, p.3, p.0)))
*/
}
case .ngon(let v):
let p = v.map { obj.positions[$0.p] }
let n = v.reduce(.zero) { $0 + obj.normals[$1.n] }.normalised
if abs(n.y) < 0.25 { continue }
if Self.isRectangle(p)
{
let left = p.map { $0.x }.min()!, right = p.map { $0.x }.max()!
let bottom = p.map { $0.y }.min()!, top = p.map { $0.y }.max()!
let back = p.map { $0.z }.min()!, forward = p.map { $0.z }.max()!
let position = Vec3f(left + right, bottom + top, back + forward) / 2.0
edge3d.append(.aabbFloor(n: n, p: position,
w: (right - left) / 2.0,
d: (forward - back) / 2.0))
}
else
{
let p0 = p[0]
for i in 1..<(v.count-1)
{
let p1 = p[i], p2 = p[i + 1]
edge3d.append(.triangle(n: n, p: (p0 + p1 + p2) / 3.0, v: (p0, p1, p2)))
}
}
default:
continue
}
}
}
func draw(_ render: Renderer, position: Vec3f)
{
var lines = [Line](
repeating: .init(from: .init(), to: .init(), colour: .zero),
count: edge3d.count * 6)
var i: Int = 0
for edge in edge3d
{
var o: Vec3f = .zero, n: Vec3f = .zero
switch edge
{
case .triangle(let trin, let trip, let triv):
o = trip
n = trin
let v0 = triv.1 - triv.0;
let v1 = triv.2 - triv.0;
let v2 = position - triv.0;
let iden = 1.0 / (v0.x * v1.z - v1.x * v0.z);
let v = (v2.x * v1.z - v1.x * v2.z) * iden;
let w = (v0.x * v2.z - v2.x * v0.z) * iden;
let colour = if v >= 0.0 && w >= 0.0 && v + w <= 1.0
{ XnaColour.Red } else { XnaColour.GreenYellow }
//let p = triv
//let det = (p.1.x - p.0.x) * (p.2.z - p.0.z) - (p.1.z - p.0.z) * (p.2.x - p.0.x)
//let colour: Colour = if
// det * (p.1.x - p.0.x) * (position.z - p.0.z) - (p.1.z - p.0.z) * (position.x - p.0.x) >= 0,
// det * (p.2.x - p.1.x) * (position.z - p.1.z) - (p.2.z - p.1.z) * (position.x - p.1.x) >= 0,
// det * (p.0.x - p.2.x) * (position.z - p.2.z) - (p.0.z - p.2.z) * (position.x - p.2.x) >= 0
/*
let side = { (v1: Vec3f, v2: Vec3f, p: Vec3f) in
(v2.z - v1.z) * (p.x - v1.x) + (v2.x + v1.x) * (position.z - v1.z) }
let colour = if
side(triv.0, triv.1, position) >= 0,
side(triv.1, triv.2, position) >= 0,
side(triv.2, triv.0, position) >= 0
*/
lines[i + 0] = Line(from: triv.0, to: triv.1, colour: colour)
lines[i + 1] = Line(from: triv.1, to: triv.2, colour: colour)
lines[i + 2] = Line(from: triv.2, to: triv.0, colour: colour)
i += 3
case .aabbFloor(let floorn, let floorp, let floorw, let floord):
o = floorp
n = floorn
let n2 = Vec2f(n.x, n.z) / n.y
let z0 = Vec2f(-floorw, floord).dot(n2)
let z1 = Vec2f(-floorw, -floord).dot(n2)
let z2 = Vec2f( floorw, -floord).dot(n2)
let z3 = Vec2f( floorw, floord).dot(n2)
let c0 = floorp + Vec3f( floorw, z0, -floord)
let c1 = floorp + Vec3f( floorw, z1, floord)
let c2 = floorp + Vec3f(-floorw, z2, floord)
let c3 = floorp + Vec3f(-floorw, z3, -floord)
lines[i + 0] = Line(from: c0, to: c1, colour: XnaColour.GreenYellow)
lines[i + 1] = Line(from: c1, to: c2, colour: XnaColour.GreenYellow)
lines[i + 2] = Line(from: c2, to: c3, colour: XnaColour.GreenYellow)
lines[i + 3] = Line(from: c3, to: c0, colour: XnaColour.GreenYellow)
i += 4
case .quad(let verts, let winding):
/*
let p = (
verts.0 + (verts.1 - verts.0) * position.x,
verts.3 + (verts.2 - verts.3) * position.x,
verts.0 + (verts.3 - verts.0) * position.z,
verts.1 + (verts.2 - verts.1) * position.z)
let xdiff = Vec2f(p.0.x - p.1.x, p.2.x - p.3.x)
let ydiff = Vec2f(p.0.z - p.1.z, p.2.z - p.3.z)
let div = xdiff.cross(ydiff)
guard div != 0.0 else { break }
let d = Vec2f(
Vec2f(p.0.x, p.0.z).cross(Vec2f(p.1.x, p.1.z)),
Vec2f(p.2.x, p.2.z).cross(Vec2f(p.3.x, p.3.z)))
let pos = Vec2f(d.cross(xdiff), d.cross(ydiff)) / div
o = Vec3f(pos.x, 0.0, pos.y)
n = .up
*/
//n = winding == .ccw ? .up : .down
o = verts.0.lerp(verts.3, 0.5).lerp(
verts.2.lerp(verts.1, 0.5), 0.5)
/*
let xy = Vec2d(Double(position.x), Double(position.z))
let a = xy.x - p.0.x
let b = p.1.x - p.0.x
let c = p.3.x - p.0.x
let d = p.0.x - p.1.x + p.2.x - p.3.x
let f = xy.y - p.0.y
let g = p.1.y - p.0.y
let h = p.3.y - p.0.y
let j = p.0.y - p.1.y + p.2.y - p.3.y
let v2 = -c * j - (-d * h)
let v1 = a * j - c * g - (d * f - b * h)
let v0 = a * g - b * f
let vq = (-v1 + sqrt(v1 * v1 - 4.0 * v2 * v0)) / (2.0 * v2)
let uq = (a - c * vq) / (b + d * vq)
let uv = Vec2d(uq, vq)
*/
var colour = XnaColour.GreenYellow
/*
p1 p2
*------*
| |
| |
*------*
p0 p3
*/
let p = winding == .ccw ? (verts.3, verts.2, verts.1, verts.0) : (verts.0, verts.1, verts.2, verts.3)
let vn = (
(verts.1 - verts.0).cross(verts.3 - verts.0),
(verts.2 - verts.1).cross(verts.0 - verts.1),
(verts.3 - verts.2).cross(verts.1 - verts.2),
(verts.0 - verts.3).cross(verts.2 - verts.3)
)
n = (vn.0 + vn.1 + vn.2 + vn.3).normalised
let uv = Self.quadSpaceFromCartesian(quad: p, position: position)
if uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0
//if uv.x >= -1.0 && uv.x <= 1.0 && uv.y >= -1.0 && uv.y <= 1.0
{
var pp = p.0
pp += (p.1 - p.0) * uv.x
pp += (p.3 - p.0) * uv.y
pp += (p.0 - p.1 + p.2 - p.3) * uv.x * uv.y
lines[i] = Line(from: o, to: pp, colour: XnaColour.Aquamarine)
i += 1
colour = XnaColour.BurlyWood
o = pp
n = vn.0.lerp(vn.3, uv.x).lerp(
vn.2.lerp(vn.1, uv.x), winding == .cw ? uv.y : 1.0 - uv.y).normalised
}
lines[i + 0] = Line(from: verts.0, to: verts.1, colour: colour)
lines[i + 1] = Line(from: verts.1, to: verts.2, colour: colour)
lines[i + 2] = Line(from: verts.2, to: verts.3, colour: colour)
lines[i + 3] = Line(from: verts.3, to: verts.0, colour: colour)
i += 4
}
let p = position
let a = p.dot(n) - o.dot(n)
let pissy = p - n * a
//let d = colin.position - edge.p
//let pissy = edge.p + d.cross(edge.n)
/*
if a > -1.0 && a <= 0.0
{
lines[i + 0] = Line(from: o, to: o + n * max(0, a), colour: XnaColour.Magenta)
lines[i + 1] = Line(from: pissy + .up, to: o, colour: XnaColour.Red)
i += 2
}
*/
lines[i + 0] = Line(from: o, to: o + n * 0.2, colour: XnaColour.Magenta)
i += 1
//lines[i + 4] = Line(from: pissy + Vec3f(-1, 0, 0) * 0.1, to: pissy + Vec3f(1, 0, 0) * 0.1, colour: XnaColour.Red)
//lines[i + 5] = Line(from: pissy + Vec3f( 0,-1, 0) * 0.1, to: pissy + Vec3f(0, 1, 0) * 0.1, colour: XnaColour.Red)
//lines[i + 6] = Line(from: pissy + Vec3f( 0, 0,-1) * 0.1, to: pissy + Vec3f(0, 0, 1) * 0.1, colour: XnaColour.Red)
}
render.drawGizmos(lines: lines)
}
}

View File

@ -0,0 +1,9 @@
import JolkEngine
protocol Actor
{
func update(deltaTime: Float, world: Collision)
var position: Vec3f { get }
var transform: Mat4f { get }
}

View File

@ -0,0 +1,276 @@
import SDL2
import simd
import OpenGL.GL
import JolkEngine
class Colin: Actor
{
var position: Vec3f { _pos }
var transform: Mat4f
{
//.rotate(yaw: angle.x, pitch: angle.y, roll: sin(time)) *
//.scale(Vec3f(1.0 + 0.25 * cos(time), 1.0 + 0.25 * sin(time), 1.0)) *
.rotate(yawPitch: angle) * .translate(-position - Vec3f(0, 1, 0))
}
var angle: Vec2f { return Vec2f(ofsAngle.x + _angle, ofsAngle.y) }
var fov: Float { return _fov }
private var time: Float = 0.0
//private var jumpVel: Float = 0.0
private var velocity: Vec3f = .zero
private var _pos: Vec3f = .zero
private var _pos2D: Vec2f { get { Vec2f(_pos.x, _pos.z) } set(new) { _pos.x = new.x; _pos.z = new.y } }
private var _angle: Float = 0.0
private var ofsAngle: Vec2f = .zero
private var _fov: Float = 60.0
private var nutted = false
private var colinMode = false
private var backPressed = false
private let colinWidth: Float = 0.2
private func move2D(new: Vec2f, edges: [Collision.Edge])
{
let velocity = new - _pos2D
var lastPos = _pos2D
_pos2D = new
var collided = -1
jolk: while (collided != 0)
{
let scabidabadoo = 10
for edge in edges
{
let diff = _pos2D - lastPos
if simd_dot(edge.n, diff) > 0 && simd_dot(edge.n, velocity) > 0 { continue }
let deltaPos = _pos2D - edge.p
let something = deltaPos.cross(edge.n)
if abs(something) * 2.0 < edge.w
{
let dot = simd_dot(edge.n, deltaPos)
if dot > 0 && dot < colinWidth
{
lastPos = _pos2D
_pos2D += edge.n * (colinWidth - dot)
if collided < 0 { collided = scabidabadoo };
}
}
else
{
let vec = (deltaPos - Vec2f(edge.n.y, -edge.n.x) * Float(signOf: something, magnitudeOf: edge.w * 0.5))
let distance2 = vec.len2
let epsilon: Float = 0.001
if distance2 < (colinWidth - epsilon) * (colinWidth - epsilon)
{
let distance = distance2.squareRoot()
lastPos = _pos2D
_pos2D += (vec / distance) * (colinWidth - epsilon - distance)
if collided < 0 { collided = scabidabadoo };
}
}
}
collided -= 1;
if collided <= 0 { break jolk }
}
}
private func response3D(plainPos o: Vec3f, plainNorm n: Vec3f)
{
let height: Float = 1.12
//let diff = _pos - lastPos
//let p = n.y > 1.0 ? _pos : (_pos + 2.0)
let ofs: Vec3f = n.y.sign == .plus ? .zero : .up * height
//let p = if n.y.sign == .plus { _pos } else { _pos + 1.0 }
let p = _pos + ofs
let a = p.dot(n) - o.dot(n)
if a > height * -0.5 && a < 0.0
{
_pos -= n * a
velocity -= velocity.project(n)
}
}
private func move3D(_ deltaTime: Float, world: Collision)
{
var lastPos = _pos
_pos += velocity * deltaTime
for edge in world.edge3d
{
switch edge
{
case .aabbFloor(let normal, let origin, let width, let depth):
//let left = min(edge.v0.x, edge.v1.x, edge.v2.x)
//let right = max(edge.v0.x, edge.v1.x, edge.v2.x)
//let back = min(edge.v0.z, edge.v1.z, edge.v2.z)
//let forward = max(edge.v0.z, edge.v1.z, edge.v2.z)
let left = origin.x - width, right = origin.x + width
let back = origin.z - depth, forward = origin.z + depth
if _pos.x < left || _pos.x > right { continue }
if _pos.z < back || _pos.z > forward { continue }
response3D(plainPos: origin, plainNorm: normal)
case .triangle(let normal, let origin, let verts):
let p = (verts.1 - verts.0, verts.2 - verts.0, _pos - verts.0)
let invDenom = 1.0 / (p.0.x * p.1.z - p.1.x * p.0.z);
let v = invDenom * (p.2.x * p.1.z - p.1.x * p.2.z);
let w = invDenom * (p.0.x * p.2.z - p.2.x * p.0.z);
let x = 1.0 - v - w
//guard v >= 0.0 && w >= 0.0 && v + w <= 1.0 else { break }
guard v >= 0.0 && w >= 0.0 && 0 <= x && x <= 1.0 else { break }
response3D(plainPos: origin, plainNorm: normal)
case .quad(let verts, let winding):
let vn = (
(verts.1 - verts.0).cross(verts.3 - verts.0),
(verts.2 - verts.1).cross(verts.0 - verts.1),
(verts.3 - verts.2).cross(verts.1 - verts.2),
(verts.0 - verts.3).cross(verts.2 - verts.3)
)
let uv = Collision.quadSpaceFromCartesian(quad:
winding == .ccw ? (verts.3, verts.2, verts.1, verts.0) : (verts.0, verts.1, verts.2, verts.3)
, position: _pos)
if uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0
{
//var pp = p.0
//pp += (p.1 - p.0) * uv.x
//pp += (p.3 - p.0) * uv.y
//pp += (p.0 - p.1 + p.2 - p.3) * uv.x * uv.y
let p = verts.0.lerp(verts.1, uv.x).lerp(
verts.3.lerp(verts.2, uv.x), winding == .cw ? uv.y : 1.0 - uv.y)
let n = vn.0.lerp(vn.3, uv.x).lerp(
vn.2.lerp(vn.1, uv.x), winding == .cw ? uv.y : 1.0 - uv.y).normalised
response3D(plainPos: Vec3f(_pos.x, p.y, _pos.z), plainNorm: n)
}
/*
let p = (
verts.0 + (verts.1 - verts.0) * _pos.x,
verts.3 + (verts.2 - verts.3) * _pos.x,
verts.0 + (verts.3 - verts.0) * _pos.z,
verts.1 + (verts.2 - verts.1) * _pos.z)
let xdiff = Vec2f(p.0.x - p.1.x, p.2.x - p.3.x)
let ydiff = Vec2f(p.0.z - p.1.z, p.2.z - p.3.z)
let div = xdiff.cross(ydiff)
guard div != 0.0 else { break }
let d = Vec2f(
Vec2f(p.0.x, p.0.z).cross(Vec2f(p.1.x, p.1.z)),
Vec2f(p.2.x, p.2.z).cross(Vec2f(p.3.x, p.3.z)))
let pos = Vec2f(d.cross(xdiff), d.cross(ydiff)) / div
*/
default: break
}
}
}
func update(deltaTime: Float, world: Collision)
{
time += deltaTime
let axisRescale = 1.0 / Float(INT16_MAX)
let getAxis = { (axis: SDL_GameControllerAxis) in
Float(SDL_GameControllerGetAxis(sdlPad, axis)) * axisRescale }
let getButton = { (btn: SDL_GameControllerButton) in
SDL_GameControllerGetButton(sdlPad, btn) == SDL_PRESSED }
let stick = Vec2f(
getAxis(SDL_CONTROLLER_AXIS_LEFTX),
getAxis(SDL_CONTROLLER_AXIS_LEFTY))
.cardinalDeadzone(min: 0.1, max: 1)
let turnSpeed = Float.pi * 2 * 0.1
if Input.instance.keyDown(.left)
{
_angle -= turnSpeed * deltaTime
}
if Input.instance.keyDown(.right)
{
_angle += turnSpeed * deltaTime
}
if stick != .zero
{
_angle += stick.x * 2.0 * turnSpeed * deltaTime
}
var moveVec: Vec2f = .zero
let speed: Float = 2
let forward = Vec2f(sin(self._angle), -cos(self._angle))
if Input.instance.keyDown(.up)
{
moveVec += forward * speed
}
if Input.instance.keyDown(.down)
{
moveVec -= forward * speed
}
if stick != .zero
{
moveVec -= forward * stick.y * speed
}
if Input.instance.keyDown(.c)
{
colinMode = !colinMode
}
let lookCone = Float.pi / 2.0
let dst = Vec2f(
getAxis(SDL_CONTROLLER_AXIS_RIGHTX),
getAxis(SDL_CONTROLLER_AXIS_RIGHTY))
.radialDeadzone(min: 0.1, max: 1) * lookCone
ofsAngle = ofsAngle.lerp(dst, 16 * deltaTime)
let targetFov = Float.lerp(60, 20, getAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT))
_fov = Float.lerp(_fov, targetFov, 20 * deltaTime)
let right = Vec2f(cos(self._angle), sin(self._angle))
if getButton(SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
{
moveVec -= right * speed
}
if getButton(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
{
moveVec += right * speed
}
let back = getButton(SDL_CONTROLLER_BUTTON_BACK)
if !backPressed && back { colinMode = !colinMode }
backPressed = back
if getButton(SDL_CONTROLLER_BUTTON_A) || Input.instance.keyDown(.n)
{
// play nut.wav
nutted = true
}
else { nutted = false }
//move2D(new: _pos2D + velocity, edges: edges)
if Input.instance.keyDown(.z) || getButton(SDL_CONTROLLER_BUTTON_B) { velocity.y = 2.0 }
//_pos.y += jumpVel * deltaTime
//if _pos.y > 0.0 { jumpVel -= 5.4 * deltaTime }
velocity.y -= 5.4 * deltaTime
velocity.x = moveVec.x
velocity.z = moveVec.y
move3D(deltaTime, world: world)
//else if _pos.y < 0.0
//{
// jumpVel = max(jumpVel, 0.0)
// _pos.y = 0.0
//}
}
}

View File

@ -0,0 +1,33 @@
import Foundation
import simd
import JolkEngine
class JolkCube: Actor
{
private var _pos: Vec3f
private var theta: Float = 0.0
init(position: Vec3f)
{
_pos = position
}
var position: Vec3f { _pos }
func update(deltaTime: Float, world: Collision)
{
theta += 15 * deltaTime
_pos.y = 1 + sin(theta * 0.25) * 0.25
}
var transform: Mat4f
{
.translate(_pos) *
.rotate(x: theta * 0.25) *
.rotate(y: Float.rad(fromDeg: theta)) *
// .rotate(axis: .X, angle: theta * 0.25) *
// .rotate(axis: .Y, angle: Float.rad(fromDeg: theta)) *
.scale(scalar: 0.25)
}
}

View File

@ -0,0 +1,33 @@
# Blender 3.6.2 MTL File: 'World.blend'
# www.blender.org
newmtl Cobblestone
Ns 437.449280
Ka 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
map_Kd cobblestone.png
map_Ks cobblestone_specular.png
map_Bump -bm 1.000000 cobblestone_normal.png
newmtl Material
Ns 167.965591
Ka 1.000000 1.000000 1.000000
Kd 0.089179 0.800000 0.000000
Ks 0.483607 0.483607 0.483607
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
newmtl MetalWall
Ns 55.588612
Ka 0.390244 0.390244 0.390244
Ks 0.573171 0.573171 0.573171
Ke 0.000000 0.000000 0.000000
Ni 9.650000
d 1.000000
illum 3
map_Kd metalwall1.jpg

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
Sources/Test/World.blend Normal file

Binary file not shown.

View File

@ -0,0 +1,148 @@
import JolkEngine
public struct XnaColour
{
public static let Transparent = Colour.zero
public static let AliceBlue = Colour(fromRgb24: 0xF0F8FF)
public static let AntiqueWhite = Colour(fromRgb24: 0xFAEBD7)
public static let Aqua = Colour(fromRgb24: 0x00FFFF)
public static let Aquamarine = Colour(fromRgb24: 0x7FFFD4)
public static let Azure = Colour(fromRgb24: 0xF0FFFF)
public static let Beige = Colour(fromRgb24: 0xF5F5DC)
public static let Bisque = Colour(fromRgb24: 0xFFE4C4)
public static let Black = Colour.black
public static let BlanchedAlmond = Colour(fromRgb24: 0xFFEBCD)
public static let Blue = Colour(fromRgb24: 0x0000FF)
public static let BlueViolet = Colour(fromRgb24: 0x8A2BE2)
public static let Brown = Colour(fromRgb24: 0xA52A2A)
public static let BurlyWood = Colour(fromRgb24: 0xDEB887)
public static let CadetBlue = Colour(fromRgb24: 0x5F9EA0)
public static let Chartreuse = Colour(fromRgb24: 0x7FFF00)
public static let Chocolate = Colour(fromRgb24: 0xD2691E)
public static let Coral = Colour(fromRgb24: 0xFF7F50)
public static let CornflowerBlue = Colour(fromRgb24: 0x6495ED)
public static let Cornsilk = Colour(fromRgb24: 0xFFF8DC)
public static let Crimson = Colour(fromRgb24: 0xDC143C)
public static let Cyan = Colour(fromRgb24: 0x00FFFF)
public static let DarkBlue = Colour(fromRgb24: 0x00008B)
public static let DarkCyan = Colour(fromRgb24: 0x008B8B)
public static let DarkGoldenrod = Colour(fromRgb24: 0xB8860B)
public static let DarkGray = Colour(fromRgb24: 0xA9A9A9)
public static let DarkGreen = Colour(fromRgb24: 0x006400)
public static let DarkKhaki = Colour(fromRgb24: 0xBDB76B)
public static let DarkMagenta = Colour(fromRgb24: 0x8B008B)
public static let DarkOliveGreen = Colour(fromRgb24: 0x556B2F)
public static let DarkOrange = Colour(fromRgb24: 0xFF8C00)
public static let DarkOrchid = Colour(fromRgb24: 0x9932CC)
public static let DarkRed = Colour(fromRgb24: 0x8B0000)
public static let DarkSalmon = Colour(fromRgb24: 0xE9967A)
public static let DarkSeaGreen = Colour(fromRgb24: 0x8FBC8B)
public static let DarkSlateBlue = Colour(fromRgb24: 0x483D8B)
public static let DarkSlateGray = Colour(fromRgb24: 0x2F4F4F)
public static let DarkTurquoise = Colour(fromRgb24: 0x00CED1)
public static let DarkViolet = Colour(fromRgb24: 0x9400D3)
public static let DeepPink = Colour(fromRgb24: 0xFF1493)
public static let DeepSkyBlue = Colour(fromRgb24: 0x00BFFF)
public static let DimGray = Colour(fromRgb24: 0x696969)
public static let DodgerBlue = Colour(fromRgb24: 0x1E90FF)
public static let Firebrick = Colour(fromRgb24: 0xB22222)
public static let FloralWhite = Colour(fromRgb24: 0xFFFAF0)
public static let ForestGreen = Colour(fromRgb24: 0x228B22)
public static let Fuchsia = Colour(fromRgb24: 0xFF00FF)
public static let Gainsboro = Colour(fromRgb24: 0xDCDCDC)
public static let GhostWhite = Colour(fromRgb24: 0xF8F8FF)
public static let Gold = Colour(fromRgb24: 0xFFD700)
public static let Goldenrod = Colour(fromRgb24: 0xDAA520)
public static let Gray = Colour(fromRgb24: 0x808080)
public static let Green = Colour(fromRgb24: 0x008000)
public static let GreenYellow = Colour(fromRgb24: 0xADFF2F)
public static let Honeydew = Colour(fromRgb24: 0xF0FFF0)
public static let HotPink = Colour(fromRgb24: 0xFF69B4)
public static let IndianRed = Colour(fromRgb24: 0xCD5C5C)
public static let Indigo = Colour(fromRgb24: 0x4B0082)
public static let Ivory = Colour(fromRgb24: 0xFFFFF0)
public static let Khaki = Colour(fromRgb24: 0xF0E68C)
public static let Lavender = Colour(fromRgb24: 0xE6E6FA)
public static let LavenderBlush = Colour(fromRgb24: 0xFFF0F5)
public static let LawnGreen = Colour(fromRgb24: 0x7CFC00)
public static let LemonChiffon = Colour(fromRgb24: 0xFFFACD)
public static let LightBlue = Colour(fromRgb24: 0xADD8E6)
public static let LightCoral = Colour(fromRgb24: 0xF08080)
public static let LightCyan = Colour(fromRgb24: 0xE0FFFF)
public static let LightGoldenrodYellow = Colour(fromRgb24: 0xFAFAD2)
public static let LightGray = Colour(fromRgb24: 0xD3D3D3)
public static let LightGreen = Colour(fromRgb24: 0x90EE90)
public static let LightPink = Colour(fromRgb24: 0xFFB6C1)
public static let LightSalmon = Colour(fromRgb24: 0xFFA07A)
public static let LightSeaGreen = Colour(fromRgb24: 0x20B2AA)
public static let LightSkyBlue = Colour(fromRgb24: 0x87CEFA)
public static let LightSlateGray = Colour(fromRgb24: 0x778899)
public static let LightSteelBlue = Colour(fromRgb24: 0xB0C4DE)
public static let LightYellow = Colour(fromRgb24: 0xFFFFE0)
public static let Lime = Colour(fromRgb24: 0x00FF00)
public static let LimeGreen = Colour(fromRgb24: 0x32CD32)
public static let Linen = Colour(fromRgb24: 0xFAF0E6)
public static let Magenta = Colour(fromRgb24: 0xFF00FF)
public static let Maroon = Colour(fromRgb24: 0x800000)
public static let MediumAquamarine = Colour(fromRgb24: 0x66CDAA)
public static let MediumBlue = Colour(fromRgb24: 0x0000CD)
public static let MediumOrchid = Colour(fromRgb24: 0xBA55D3)
public static let MediumPurple = Colour(fromRgb24: 0x9370DB)
public static let MediumSeaGreen = Colour(fromRgb24: 0x3CB371)
public static let MediumSlateBlue = Colour(fromRgb24: 0x7B68EE)
public static let MediumSpringGreen = Colour(fromRgb24: 0x00FA9A)
public static let MediumTurquoise = Colour(fromRgb24: 0x48D1CC)
public static let MediumVioletRed = Colour(fromRgb24: 0xC71585)
public static let MidnightBlue = Colour(fromRgb24: 0x191970)
public static let MintCream = Colour(fromRgb24: 0xF5FFFA)
public static let MistyRose = Colour(fromRgb24: 0xFFE4E1)
public static let Moccasin = Colour(fromRgb24: 0xFFE4B5)
public static let MonoGameOrange = Colour(fromRgb24: 0xE73C00)
public static let NavajoWhite = Colour(fromRgb24: 0xFFDEAD)
public static let Navy = Colour(fromRgb24: 0x000080)
public static let OldLace = Colour(fromRgb24: 0xFDF5E6)
public static let Olive = Colour(fromRgb24: 0x808000)
public static let OliveDrab = Colour(fromRgb24: 0x6B8E23)
public static let Orange = Colour(fromRgb24: 0xFFA500)
public static let OrangeRed = Colour(fromRgb24: 0xFF4500)
public static let Orchid = Colour(fromRgb24: 0xDA70D6)
public static let PaleGoldenrod = Colour(fromRgb24: 0xEEE8AA)
public static let PaleGreen = Colour(fromRgb24: 0x98FB98)
public static let PaleTurquoise = Colour(fromRgb24: 0xAFEEEE)
public static let PaleVioletRed = Colour(fromRgb24: 0xDB7093)
public static let PapayaWhip = Colour(fromRgb24: 0xFFEFD5)
public static let PeachPuff = Colour(fromRgb24: 0xFFDAB9)
public static let Peru = Colour(fromRgb24: 0xCD853F)
public static let Pink = Colour(fromRgb24: 0xFFC0CB)
public static let Plum = Colour(fromRgb24: 0xDDA0DD)
public static let PowderBlue = Colour(fromRgb24: 0xB0E0E6)
public static let Purple = Colour(fromRgb24: 0x800080)
public static let Red = Colour(fromRgb24: 0xFF0000)
public static let RosyBrown = Colour(fromRgb24: 0xBC8F8F)
public static let RoyalBlue = Colour(fromRgb24: 0x4169E1)
public static let SaddleBrown = Colour(fromRgb24: 0x8B4513)
public static let Salmon = Colour(fromRgb24: 0xFA8072)
public static let SandyBrown = Colour(fromRgb24: 0xF4A460)
public static let SeaGreen = Colour(fromRgb24: 0x2E8B57)
public static let SeaShell = Colour(fromRgb24: 0xFFF5EE)
public static let Sienna = Colour(fromRgb24: 0xA0522D)
public static let Silver = Colour(fromRgb24: 0xC0C0C0)
public static let SkyBlue = Colour(fromRgb24: 0x87CEEB)
public static let SlateBlue = Colour(fromRgb24: 0x6A5ACD)
public static let SlateGray = Colour(fromRgb24: 0x708090)
public static let Snow = Colour(fromRgb24: 0xFFFAFA)
public static let SpringGreen = Colour(fromRgb24: 0x00FF7F)
public static let SteelBlue = Colour(fromRgb24: 0x4682B4)
public static let Tan = Colour(fromRgb24: 0xD2B48C)
public static let Teal = Colour(fromRgb24: 0x008080)
public static let Thistle = Colour(fromRgb24: 0xD8BFD8)
public static let Tomato = Colour(fromRgb24: 0xFF6347)
public static let Turquoise = Colour(fromRgb24: 0x40E0D0)
public static let Violet = Colour(fromRgb24: 0xEE82EE)
public static let Wheat = Colour(fromRgb24: 0xF5DEB3)
public static let White = Colour.white
public static let WhiteSmoke = Colour(fromRgb24: 0xF5F5F5)
public static let Yellow = Colour(fromRgb24: 0xFFFF00)
public static let YellowGreen = Colour(fromRgb24: 0x9ACD32)
}