mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 13:11:33 +00:00
initial voxel implementation
This commit is contained in:
@ -3,6 +3,8 @@ add_executable(Voxelotl MACOSX_BUNDLE
|
|||||||
|
|
||||||
test.png
|
test.png
|
||||||
|
|
||||||
|
Chunk.swift
|
||||||
|
|
||||||
shadertypes.h
|
shadertypes.h
|
||||||
shader.metal
|
shader.metal
|
||||||
|
|
||||||
|
57
Sources/Voxelotl/Chunk.swift
Normal file
57
Sources/Voxelotl/Chunk.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
public struct Chunk {
|
||||||
|
public static let chunkSize: Int = 16
|
||||||
|
|
||||||
|
public let position: SIMD3<Int>
|
||||||
|
private var blocks: [Block]
|
||||||
|
|
||||||
|
init(position: SIMD3<Int>, blocks: [Block]) {
|
||||||
|
self.position = position
|
||||||
|
self.blocks = blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
init(position: SIMD3<Int>) {
|
||||||
|
self.position = position
|
||||||
|
self.blocks = Array(
|
||||||
|
repeating: BlockType.air,
|
||||||
|
count: Chunk.chunkSize * Chunk.chunkSize * Chunk.chunkSize
|
||||||
|
).map { type in Block(type) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBlockInternally(at position: SIMD3<Int>) -> Block {
|
||||||
|
blocks[position.x + position.y * Chunk.chunkSize + position.z * Chunk.chunkSize * Chunk.chunkSize]
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func setBlockInternally(at position: SIMD3<Int>, type: BlockType) {
|
||||||
|
blocks[position.x + position.y * Chunk.chunkSize + position.z * Chunk.chunkSize * Chunk.chunkSize].type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func fill(allBy calculation: () -> BlockType) {
|
||||||
|
blocks.indices.forEach { i in
|
||||||
|
blocks[i].type = calculation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forEach(block perform: (SIMD3<Int>, Block) -> Void) {
|
||||||
|
for x in 0..<Chunk.chunkSize {
|
||||||
|
for y in 0..<Chunk.chunkSize {
|
||||||
|
for z in 0..<Chunk.chunkSize {
|
||||||
|
perform(SIMD3(x, y, z), blocks[x + y * Chunk.chunkSize + z * Chunk.chunkSize * Chunk.chunkSize])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BlockType: Equatable {
|
||||||
|
case air
|
||||||
|
case solid(Color<Float16>)
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Block {
|
||||||
|
public var type: BlockType
|
||||||
|
|
||||||
|
|
||||||
|
public init(_ type: BlockType) {
|
||||||
|
self.type = type
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import simd
|
import simd
|
||||||
|
import Foundation
|
||||||
|
|
||||||
struct Box {
|
struct Box {
|
||||||
var geometry: AABB
|
var geometry: AABB
|
||||||
@ -24,26 +25,54 @@ struct Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let boxes: [Box] = [
|
|
||||||
Box(geometry: .fromUnitCube(
|
|
||||||
position: .init( 0, -1, 0) * 2,
|
|
||||||
scale: .init(10, 0.1, 10) * 2)),
|
|
||||||
Box(geometry: .fromUnitCube(
|
|
||||||
position: .init(-2.5, 0, -3) * 2,
|
|
||||||
scale: .init(repeating: 2)),
|
|
||||||
color: .init(rgb888: 0xFF80BF).linear),
|
|
||||||
Box(geometry: .fromUnitCube(
|
|
||||||
position: .init(-2.5, -0.5, -5) * 2,
|
|
||||||
scale: .init(repeating: 2)),
|
|
||||||
color: .init(rgb888: 0xBFFFFF).linear)
|
|
||||||
]
|
|
||||||
|
|
||||||
class Game: GameDelegate {
|
class Game: GameDelegate {
|
||||||
private var fpsCalculator = FPSCalculator()
|
private var fpsCalculator = FPSCalculator()
|
||||||
var camera = Camera(fov: 60, size: .one, range: 0.06...50)
|
var camera = Camera(fov: 60, size: .one, range: 0.06...900)
|
||||||
var player = Player()
|
var player = Player()
|
||||||
var projection: matrix_float4x4 = .identity
|
var projection: matrix_float4x4 = .identity
|
||||||
|
|
||||||
|
var boxes: [Box] = []
|
||||||
|
|
||||||
|
init() {
|
||||||
|
var chunk = Chunk(position: .zero)
|
||||||
|
let options: [BlockType] = [
|
||||||
|
.air,
|
||||||
|
.solid(.blue),
|
||||||
|
.air,
|
||||||
|
.solid(.red),
|
||||||
|
.air,
|
||||||
|
.solid(.green),
|
||||||
|
.air,
|
||||||
|
.solid(.white),
|
||||||
|
.air,
|
||||||
|
.solid(.cyan),
|
||||||
|
.air,
|
||||||
|
.solid(.yellow),
|
||||||
|
.air,
|
||||||
|
.solid(.magenta),
|
||||||
|
.air,
|
||||||
|
]
|
||||||
|
chunk
|
||||||
|
.fill(allBy: { options[Int(arc4random_uniform(UInt32(options.count)))] })
|
||||||
|
chunk.forEach { position, block in
|
||||||
|
if block.type == .air {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if case let .solid(color) = block.type {
|
||||||
|
boxes
|
||||||
|
.append(
|
||||||
|
Box(
|
||||||
|
geometry:
|
||||||
|
.fromUnitCube(position: SIMD3<Float>(position) + 0.5, scale: .init(repeating: 0.5)),
|
||||||
|
color: color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
func fixedUpdate(_ time: GameTime) {
|
func fixedUpdate(_ time: GameTime) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -74,7 +103,7 @@ class Game: GameDelegate {
|
|||||||
}
|
}
|
||||||
instances.append(
|
instances.append(
|
||||||
Instance(
|
Instance(
|
||||||
position: .init(0, sin(totalTime * 1.5 * cubeSpeedMul) * 0.5, -2) * 2,
|
position: .init(0, sin(totalTime * 1.5 * cubeSpeedMul) * 0.5, 0) * 2,
|
||||||
scale: .init(repeating: 0.5),
|
scale: .init(repeating: 0.5),
|
||||||
rotation: .init(angle: totalTime * 3.0 * cubeSpeedMul, axis: .init(0, 1, 0)),
|
rotation: .init(angle: totalTime * 3.0 * cubeSpeedMul, axis: .init(0, 1, 0)),
|
||||||
color: .init(r: 0.5, g: 0.5, b: 1).linear))
|
color: .init(r: 0.5, g: 0.5, b: 1).linear))
|
||||||
|
@ -20,7 +20,9 @@ struct Player {
|
|||||||
|
|
||||||
private var _onGround: Bool = false
|
private var _onGround: Bool = false
|
||||||
|
|
||||||
public var position: SIMD3<Float> { self._position + .init(0, Self.eyeLevel, 0) }
|
public var position: SIMD3<Float> {
|
||||||
|
get { self._position + .init(0, Self.eyeLevel, 0) } set { self._position = newValue }
|
||||||
|
}
|
||||||
public var rotation: SIMD2<Float> { self._rotation }
|
public var rotation: SIMD2<Float> { self._rotation }
|
||||||
|
|
||||||
mutating func update(deltaTime: Float, boxes: [Box]) {
|
mutating func update(deltaTime: Float, boxes: [Box]) {
|
||||||
@ -36,13 +38,18 @@ struct Player {
|
|||||||
}
|
}
|
||||||
self._rotation.y = self._rotation.y.clamp(-.pi * 0.5, .pi * 0.5)
|
self._rotation.y = self._rotation.y.clamp(-.pi * 0.5, .pi * 0.5)
|
||||||
|
|
||||||
if self._onGround {
|
// Movement (slower in air than on ground)
|
||||||
// Movement on ground
|
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
||||||
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
||||||
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
let movementScale: Float = self._onGround ? 1.0 : 0.4
|
||||||
self._velocity.x = (movement.x * rotc - movement.y * rots) * Self.accelerationCoeff
|
self._velocity.x = (
|
||||||
self._velocity.z = (movement.y * rotc + movement.x * rots) * Self.accelerationCoeff
|
movement.x * rotc - movement.y * rots
|
||||||
|
) * Self.accelerationCoeff * movementScale
|
||||||
|
self._velocity.z = (
|
||||||
|
movement.y * rotc + movement.x * rots
|
||||||
|
) * Self.accelerationCoeff * movementScale
|
||||||
|
|
||||||
|
if self._onGround {
|
||||||
// Jumping
|
// Jumping
|
||||||
if pad.pressed(.east) {
|
if pad.pressed(.east) {
|
||||||
self._velocity.y = Self.jumpVelocity
|
self._velocity.y = Self.jumpVelocity
|
||||||
@ -50,8 +57,8 @@ struct Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flying
|
// Flying and unflying
|
||||||
self._velocity.y += pad.rightTrigger * 36 * deltaTime
|
self._velocity.y += (pad.rightTrigger - pad.leftTrigger) * 36 * deltaTime
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
if pad.pressed(.back) {
|
if pad.pressed(.back) {
|
||||||
@ -112,5 +119,17 @@ struct Player {
|
|||||||
self._velocity.x = 0
|
self._velocity.x = 0
|
||||||
self._velocity.z = 0
|
self._velocity.z = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self._velocity.x > 10 {
|
||||||
|
self._velocity.x = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
if self._velocity.y > 10 {
|
||||||
|
self._velocity.y = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
if abs(self._velocity.y) > 40 {
|
||||||
|
self._velocity.y = Float(signOf: self._velocity.y, magnitudeOf: 40.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user