textured voxel terrain
This commit is contained in:
parent
ab35890f1b
commit
968c6ff3ad
@ -35,7 +35,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
totalDiffuse = max(totalDiffuse,0.2);
|
totalDiffuse = max(totalDiffuse,0.2);
|
||||||
|
|
||||||
vec4 textureColor = texture2D(texture0, uv * 40.0);
|
vec4 textureColor = texture2D(texture0, uv);
|
||||||
if(textureColor.a<0.5){
|
if(textureColor.a<0.5){
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
BIN
assets/textures/voxel.png
Normal file
BIN
assets/textures/voxel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -143,6 +143,8 @@ class Camera extends Node {
|
|||||||
vec3.multiply(vec, this.right, velocity)
|
vec3.multiply(vec, this.right, velocity)
|
||||||
vec3.add(this.pos, this.pos, vec)
|
vec3.add(this.pos, this.pos, vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.frustum.construct(mat4.multiply([], this.projection, this.view))
|
||||||
}
|
}
|
||||||
|
|
||||||
processMouseMove (offset, constrain = true) {
|
processMouseMove (offset, constrain = true) {
|
||||||
|
@ -17,8 +17,7 @@ class PlanetGenerator {
|
|||||||
return this.noise.getNoise3D(detail, normal[0], normal[1], normal[2])
|
return this.noise.getNoise3D(detail, normal[0], normal[1], normal[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
getBiome (detail, normal) {
|
getBiome (height, normal) {
|
||||||
const heightAtPoint = this.getHeight(detail, normal)
|
|
||||||
// const moistureAtPoint = this.moisture.getNoise3D(5, normal)
|
// const moistureAtPoint = this.moisture.getNoise3D(5, normal)
|
||||||
|
|
||||||
// 0 - hot, 1 - cold
|
// 0 - hot, 1 - cold
|
||||||
@ -27,12 +26,10 @@ class PlanetGenerator {
|
|||||||
const poleTemp = 0.4
|
const poleTemp = 0.4
|
||||||
// TODO: pole settings for planet
|
// TODO: pole settings for planet
|
||||||
const distanceFromPoles = Math.abs(vec3.dot(normal, [0.0, 1.0, 0.0]))
|
const distanceFromPoles = Math.abs(vec3.dot(normal, [0.0, 1.0, 0.0]))
|
||||||
|
|
||||||
let e = heightAtPoint
|
|
||||||
// Calculate temperature for the poles
|
// Calculate temperature for the poles
|
||||||
e = (e * e + poleTemp + (equatorTemp - poleTemp) * distanceFromPoles)
|
const e = (height * height + poleTemp + (equatorTemp - poleTemp) * distanceFromPoles)
|
||||||
|
|
||||||
if (heightAtPoint < 0.1) return [1 / 255, 56 / 255, 104 / 255] // Water
|
if (height < 0.1) return [1 / 255, 56 / 255, 104 / 255] // Water
|
||||||
else if (e <= 0.8) return [44 / 255, 50 / 255, 29 / 255] // Grass
|
else if (e <= 0.8) return [44 / 255, 50 / 255, 29 / 255] // Grass
|
||||||
else if (e < 0.9) return [50 / 255, 50 / 255, 50 / 255] // Stone
|
else if (e < 0.9) return [50 / 255, 50 / 255, 50 / 255] // Stone
|
||||||
else return [1, 1, 1] // Snow
|
else return [1, 1, 1] // Snow
|
||||||
@ -176,7 +173,7 @@ class CubeFace {
|
|||||||
const pointHeight = this.generator.getHeight(this.level + 1, normal)
|
const pointHeight = this.generator.getHeight(this.level + 1, normal)
|
||||||
const pos = mulv3(normal, pointHeight * 10 + radius)
|
const pos = mulv3(normal, pointHeight * 10 + radius)
|
||||||
|
|
||||||
const pointBiome = this.generator.getBiome(this.level + 1, normal)
|
const pointBiome = this.generator.getBiome(pointHeight, normal)
|
||||||
|
|
||||||
vertices[vertexPointer * 3] = pos[0]
|
vertices[vertexPointer * 3] = pos[0]
|
||||||
vertices[vertexPointer * 3 + 1] = pos[1]
|
vertices[vertexPointer * 3 + 1] = pos[1]
|
||||||
@ -255,6 +252,7 @@ class CubeFace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
|
if (!this.visible) return
|
||||||
if (!this.mesh) {
|
if (!this.mesh) {
|
||||||
for (const i in this.children) {
|
for (const i in this.children) {
|
||||||
this.children[i].draw(gl, shader)
|
this.children[i].draw(gl, shader)
|
||||||
@ -262,16 +260,16 @@ class CubeFace {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.visible) return
|
|
||||||
|
|
||||||
CubeFace.determineIndexBuffer(this)
|
CubeFace.determineIndexBuffer(this)
|
||||||
|
|
||||||
this.mesh.prepare(gl, shader)
|
this.mesh.prepare(gl, shader)
|
||||||
|
|
||||||
if (this.mesh.cbuffer && shader.hasAttribute(gl, 'aColor')) {
|
if (this.mesh.cbuffer && shader.hasAttribute(gl, 'aColor')) {
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.mesh.cbuffer)
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.mesh.cbuffer)
|
||||||
shader.setAttribute(gl, 'aColor', 3, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0)
|
shader.setAttribute(gl, 'aColor', 3, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0)
|
||||||
this.mesh._bufferCount++
|
this.mesh._bufferCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ class DirectionalLight extends SpotLight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Environment {
|
class Environment {
|
||||||
constructor (ambient) {
|
constructor (ambient, sun) {
|
||||||
this.ambient = ambient
|
this.ambient = ambient
|
||||||
|
|
||||||
this.fogStart = 0
|
this.fogStart = 0
|
||||||
this.fogEnd = 0
|
this.fogEnd = 0
|
||||||
this.fogColor = [0.8, 0.8, 0.8]
|
this.fogColor = [0.8, 0.8, 0.8]
|
||||||
|
|
||||||
this.sun = new Light([0.0, 10000.0, -20000.0], [1.0, 1.0, 1.0])
|
this.sun = sun
|
||||||
this.lights = [this.sun]
|
this.lights = [this.sun]
|
||||||
|
|
||||||
this.maxEnvironmentLights = ENV_MAX_LIGHTS
|
this.maxEnvironmentLights = ENV_MAX_LIGHTS
|
||||||
|
@ -84,6 +84,7 @@ class Material {
|
|||||||
const tex = this.textures[i]
|
const tex = this.textures[i]
|
||||||
if (tex && tex instanceof Texture) {
|
if (tex && tex instanceof Texture) {
|
||||||
gl.activeTexture(gl.TEXTURE0 + parseInt(i))
|
gl.activeTexture(gl.TEXTURE0 + parseInt(i))
|
||||||
|
|
||||||
gl.bindTexture(tex.type, tex.id)
|
gl.bindTexture(tex.type, tex.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Mesh } from '../mesh'
|
import { Mesh } from '../mesh'
|
||||||
import { Node, MeshInstance } from '../components'
|
import { MeshInstance } from '../components'
|
||||||
import { vec3 } from 'gl-matrix'
|
import { vec3 } from 'gl-matrix'
|
||||||
import { addv3, subv3, mulv3, dim3to1, dim1to3 } from '../utility'
|
import { addv3, subv3, dim3to1 } from '../utility'
|
||||||
import { BoundingBox } from '../mesh/aabb'
|
|
||||||
import VoxelData from './voxeldata'
|
import VoxelData from './voxeldata'
|
||||||
|
import VoxelTexture from './voxeltexture'
|
||||||
|
|
||||||
const FACE_VERTEX = [
|
const FACE_VERTEX = [
|
||||||
// Bottom
|
// Bottom
|
||||||
@ -24,34 +24,34 @@ const FACE_VERTEX = [
|
|||||||
],
|
],
|
||||||
// Left
|
// Left
|
||||||
[
|
[
|
||||||
[0.0, 0.0, 1.0],
|
|
||||||
[0.0, 1.0, 1.0],
|
|
||||||
[0.0, 1.0, 0.0],
|
[0.0, 1.0, 0.0],
|
||||||
[0.0, 0.0, 0.0],
|
[0.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 1.0],
|
||||||
|
[0.0, 1.0, 1.0],
|
||||||
[-1.0, 0.0, 0.0]
|
[-1.0, 0.0, 0.0]
|
||||||
],
|
],
|
||||||
// Right
|
// Right
|
||||||
[
|
[
|
||||||
[1.0, 0.0, 0.0],
|
|
||||||
[1.0, 1.0, 0.0],
|
|
||||||
[1.0, 1.0, 1.0],
|
[1.0, 1.0, 1.0],
|
||||||
[1.0, 0.0, 1.0],
|
[1.0, 0.0, 1.0],
|
||||||
|
[1.0, 0.0, 0.0],
|
||||||
|
[1.0, 1.0, 0.0],
|
||||||
[1.0, 0.0, 0.0]
|
[1.0, 0.0, 0.0]
|
||||||
],
|
],
|
||||||
// Front
|
// Front
|
||||||
[
|
[
|
||||||
[1.0, 0.0, 1.0],
|
|
||||||
[1.0, 1.0, 1.0],
|
|
||||||
[0.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0],
|
||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
|
[1.0, 0.0, 1.0],
|
||||||
|
[1.0, 1.0, 1.0],
|
||||||
[0.0, 0.0, -1.0]
|
[0.0, 0.0, -1.0]
|
||||||
],
|
],
|
||||||
// Back
|
// Back
|
||||||
[
|
[
|
||||||
[0.0, 0.0, 0.0],
|
|
||||||
[0.0, 1.0, 0.0],
|
|
||||||
[1.0, 1.0, 0.0],
|
[1.0, 1.0, 0.0],
|
||||||
[1.0, 0.0, 0.0],
|
[1.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0],
|
||||||
[0.0, 0.0, 1.0]
|
[0.0, 0.0, 1.0]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -63,8 +63,10 @@ const FACE_RIGHT = 3
|
|||||||
const FACE_FRONT = 4
|
const FACE_FRONT = 4
|
||||||
const FACE_BACK = 5
|
const FACE_BACK = 5
|
||||||
|
|
||||||
const AIR_VOXEL = VoxelData.register('air', { solid: false })
|
const AIR = VoxelData.register('air', { solid: false })
|
||||||
const GROUND_VOXEL = VoxelData.register('ground', { solid: true })
|
const GRASS = VoxelData.register('grass', { solid: true, tiles: [0, 2, 1, 1, 1, 1] })
|
||||||
|
const DIRT = VoxelData.register('dirt', { solid: true, tiles: [0] })
|
||||||
|
const STONE = VoxelData.register('stone', { solid: true, tiles: [3] })
|
||||||
|
|
||||||
class VoxelChunk extends MeshInstance {
|
class VoxelChunk extends MeshInstance {
|
||||||
constructor (world, pos, size = 16) {
|
constructor (world, pos, size = 16) {
|
||||||
@ -85,6 +87,11 @@ class VoxelChunk extends MeshInstance {
|
|||||||
|
|
||||||
// If the chunk is outside of the view, make it inactive
|
// If the chunk is outside of the view, make it inactive
|
||||||
this.active = true
|
this.active = true
|
||||||
|
|
||||||
|
this.bounds = [
|
||||||
|
vec3.transformMat4([], [0.0, 0.0, 0.0], this.transform),
|
||||||
|
vec3.transformMat4([], [this.size, this.size, this.size], this.transform)
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
getVoxel (x, y, z) {
|
getVoxel (x, y, z) {
|
||||||
@ -95,41 +102,41 @@ class VoxelChunk extends MeshInstance {
|
|||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(this.size + x, y, z)
|
return neighbor.getVoxel(this.size + x, y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
} else if (x >= this.size) {
|
} else if (x >= this.size) {
|
||||||
neighbor = this.world.getChunk(this.relativePos[0] + 1, this.relativePos[1], this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0] + 1, this.relativePos[1], this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x - this.size, y, z)
|
return neighbor.getVoxel(x - this.size, y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
} else if (y < 0) {
|
} else if (y < 0) {
|
||||||
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] - 1, this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] - 1, this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, this.size + y, z)
|
return neighbor.getVoxel(x, this.size + y, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
} else if (y >= this.size) {
|
} else if (y >= this.size) {
|
||||||
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] + 1, this.relativePos[2])
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1] + 1, this.relativePos[2])
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y - this.size, z)
|
return neighbor.getVoxel(x, y - this.size, z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
} else if (z < 0) {
|
} else if (z < 0) {
|
||||||
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] - 1)
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] - 1)
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y, this.size + z)
|
return neighbor.getVoxel(x, y, this.size + z)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
} else if (z >= this.size) {
|
} else if (z >= this.size) {
|
||||||
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] + 1)
|
neighbor = this.world.getChunk(this.relativePos[0], this.relativePos[1], this.relativePos[2] + 1)
|
||||||
if (neighbor) {
|
if (neighbor) {
|
||||||
return neighbor.getVoxel(x, y, z - this.size)
|
return neighbor.getVoxel(x, y, z - this.size)
|
||||||
}
|
}
|
||||||
return AIR_VOXEL
|
return AIR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.data[dim3to1(x, y, z, this.size)] || AIR_VOXEL
|
return this.data[dim3to1(x, y, z, this.size)] || AIR
|
||||||
}
|
}
|
||||||
|
|
||||||
getVoxelv (v) {
|
getVoxelv (v) {
|
||||||
@ -137,13 +144,18 @@ class VoxelChunk extends MeshInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generate (generator) {
|
generate (generator) {
|
||||||
this.material = generator.material
|
this.material = VoxelTexture.material
|
||||||
for (let x = 0; x < this.size; x++) {
|
for (let x = 0; x < this.size; x++) {
|
||||||
for (let z = 0; z < this.size; z++) {
|
for (let z = 0; z < this.size; z++) {
|
||||||
const columnHeight = generator.getHeight(x + this.pos[0], z + this.pos[2])
|
const columnHeight = Math.floor(generator.getHeight(x + this.pos[0], z + this.pos[2]))
|
||||||
for (let y = 0; y < this.size; y++) {
|
for (let y = 0; y < this.size; y++) {
|
||||||
const solid = this.pos[1] + y < columnHeight
|
let voxel = AIR
|
||||||
this.data[dim3to1(x, y, z, this.size)] = solid ? GROUND_VOXEL : AIR_VOXEL
|
|
||||||
|
if (this.pos[1] + y === columnHeight) voxel = GRASS
|
||||||
|
else if (this.pos[1] + y < columnHeight - 3) voxel = STONE
|
||||||
|
else if (this.pos[1] + y < columnHeight) voxel = DIRT
|
||||||
|
|
||||||
|
this.data[dim3to1(x, y, z, this.size)] = voxel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +166,7 @@ class VoxelChunk extends MeshInstance {
|
|||||||
|
|
||||||
// Programmatically generate a voxel face
|
// Programmatically generate a voxel face
|
||||||
// Returns the position, normal and texture coordinates for each vertex in this face
|
// Returns the position, normal and texture coordinates for each vertex in this face
|
||||||
createFace (indices, points, pos, face) {
|
createFace (indices, points, pos, vId, face) {
|
||||||
// Add the corresponding offsets for this face to the position
|
// Add the corresponding offsets for this face to the position
|
||||||
const corners = [
|
const corners = [
|
||||||
addv3(pos, FACE_VERTEX[face][0]), addv3(pos, FACE_VERTEX[face][1]),
|
addv3(pos, FACE_VERTEX[face][0]), addv3(pos, FACE_VERTEX[face][1]),
|
||||||
@ -163,14 +175,15 @@ class VoxelChunk extends MeshInstance {
|
|||||||
|
|
||||||
// Select the normal for this face
|
// Select the normal for this face
|
||||||
const normal = FACE_VERTEX[face][4]
|
const normal = FACE_VERTEX[face][4]
|
||||||
|
const uvs = VoxelData.textureIndex(vId, face)
|
||||||
|
|
||||||
// Create the 4 vertices that make up this face
|
// Create the 4 vertices that make up this face
|
||||||
// They're named points because this function returns not only vertices,
|
// They're named points because this function returns not only vertices,
|
||||||
// but corresponding texture coordinates and normals at the same time for convenience
|
// but corresponding texture coordinates and normals at the same time for convenience
|
||||||
points.push([corners[0], normal, [0.0, 1.0]])
|
points.push([corners[0], normal, uvs[1]])
|
||||||
points.push([corners[1], normal, [0.0, 0.0]])
|
points.push([corners[1], normal, uvs[0]])
|
||||||
points.push([corners[2], normal, [1.0, 0.0]])
|
points.push([corners[2], normal, uvs[2]])
|
||||||
points.push([corners[3], normal, [1.0, 1.0]])
|
points.push([corners[3], normal, uvs[3]])
|
||||||
|
|
||||||
// Create the face
|
// Create the face
|
||||||
const inx = points.length - 4
|
const inx = points.length - 4
|
||||||
@ -203,30 +216,31 @@ class VoxelChunk extends MeshInstance {
|
|||||||
for (let y = 0; y < this.size; y++) {
|
for (let y = 0; y < this.size; y++) {
|
||||||
for (let z = 0; z < this.size; z++) {
|
for (let z = 0; z < this.size; z++) {
|
||||||
const cellPos = [x, y, z]
|
const cellPos = [x, y, z]
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x, y, z))) continue
|
const vid = this.getVoxel(x, y, z)
|
||||||
|
if (!VoxelData.isSolid(vid)) continue
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x, y - 1, z))) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y - 1, z))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_BOTTOM)
|
this.createFace(indices, points, cellPos, vid, FACE_BOTTOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x, y + 1, z))) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y + 1, z))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_TOP)
|
this.createFace(indices, points, cellPos, vid, FACE_TOP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x - 1, y, z))) {
|
if (!VoxelData.isSolid(this.getVoxel(x - 1, y, z))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_LEFT)
|
this.createFace(indices, points, cellPos, vid, FACE_LEFT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x + 1, y, z))) {
|
if (!VoxelData.isSolid(this.getVoxel(x + 1, y, z))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_RIGHT)
|
this.createFace(indices, points, cellPos, vid, FACE_RIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x, y, z + 1))) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y, z + 1))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_FRONT)
|
this.createFace(indices, points, cellPos, vid, FACE_FRONT)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VoxelData.isSolid(this.getVoxel(x, y, z - 1))) {
|
if (!VoxelData.isSolid(this.getVoxel(x, y, z - 1))) {
|
||||||
this.createFace(indices, points, cellPos, FACE_BACK)
|
this.createFace(indices, points, cellPos, vid, FACE_BACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,10 +276,7 @@ class VoxelChunk extends MeshInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update (gl, dt, camera) {
|
update (gl, dt, camera) {
|
||||||
this.active = camera.frustum.containsBox(
|
if (this.bounds.length) this.active = camera.frustum.containsBox(this.bounds[0], this.bounds[1])
|
||||||
vec3.transformMat4([], [0.0, 0.0, 0.0], this.transform),
|
|
||||||
vec3.transformMat4([], [this.size, this.size, this.size], this.transform)
|
|
||||||
)
|
|
||||||
if (!this.active) return false
|
if (!this.active) return false
|
||||||
if (!this.generated) return this.generate(this.world.generator)
|
if (!this.generated) return this.generate(this.world.generator)
|
||||||
if (this.dirty) return this.createMesh(gl)
|
if (this.dirty) return this.createMesh(gl)
|
||||||
@ -352,8 +363,7 @@ class VoxelWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VoxelGenerator {
|
class VoxelGenerator {
|
||||||
constructor (noise, material, groundHeight = 64) {
|
constructor (noise, groundHeight = 64) {
|
||||||
this.material = material
|
|
||||||
this.noise = noise
|
this.noise = noise
|
||||||
this.groundHeight = groundHeight
|
this.groundHeight = groundHeight
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import VoxelTexture from './voxeltexture'
|
||||||
|
|
||||||
|
const MISSING_UV = [[0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]]
|
||||||
|
|
||||||
const VoxelData = {
|
const VoxelData = {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -12,15 +15,22 @@ const VoxelData = {
|
|||||||
},
|
},
|
||||||
get: (name) => {
|
get: (name) => {
|
||||||
return VoxelData.registeredVoxels[name]
|
return VoxelData.registeredVoxels[name]
|
||||||
},
|
|
||||||
afterRegistration: () => {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
isSolid: (id) => {
|
isSolid: (id) => {
|
||||||
return VoxelData.indexCache[id] ? VoxelData.indexCache[id].solid : false
|
return VoxelData.indexCache[id] ? VoxelData.indexCache[id].solid : false
|
||||||
},
|
},
|
||||||
textureIndex: (id, face) => {
|
textureIndex: (id, face) => {
|
||||||
|
const icache = VoxelData.indexCache[id]
|
||||||
|
if (!icache.tiles) return MISSING_UV
|
||||||
|
if (icache.tiles.length === 1) return VoxelTexture.faceUVs(icache.tiles[0])
|
||||||
|
if (icache.tiles.length >= 2 && icache.tiles.length < 6) {
|
||||||
|
// top face
|
||||||
|
if (face === 1) {
|
||||||
|
return VoxelTexture.faceUVs(icache.tiles[0])
|
||||||
|
}
|
||||||
|
return VoxelTexture.faceUVs(icache.tiles[1])
|
||||||
|
}
|
||||||
|
return VoxelTexture.faceUVs(icache.tiles[face]) || MISSING_UV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
import Screen from '../screen'
|
import Screen from '../screen'
|
||||||
|
import { Texture, Material } from '../mesh/material'
|
||||||
|
|
||||||
function generateTextureMap (registeredVoxels) {
|
const clip = 1 / 100
|
||||||
// body...
|
|
||||||
}
|
|
||||||
|
|
||||||
const VoxelTexture = {
|
const VoxelTexture = {
|
||||||
|
size: 0,
|
||||||
|
voxelSize: 0,
|
||||||
|
texture: null,
|
||||||
|
material: null,
|
||||||
|
loadFromFile: async (fileName, size) => {
|
||||||
|
VoxelTexture.texture = await Texture.fromFile(Screen.gl, fileName, true, Screen.gl.NEAREST, Screen.gl.CLAMP_TO_EDGE)
|
||||||
|
VoxelTexture.size = size
|
||||||
|
VoxelTexture.voxelSize = 1 / size
|
||||||
|
VoxelTexture.material = new Material([VoxelTexture.texture])
|
||||||
|
},
|
||||||
|
faceUVs: (textureIndex) => {
|
||||||
|
let x = textureIndex / VoxelTexture.size
|
||||||
|
let y = textureIndex - (x * VoxelTexture.size)
|
||||||
|
|
||||||
|
y = 1 - y - VoxelTexture.voxelSize
|
||||||
|
|
||||||
|
return [
|
||||||
|
[x + clip, y + clip],
|
||||||
|
[x + clip, y + VoxelTexture.voxelSize - clip],
|
||||||
|
[x - clip + VoxelTexture.voxelSize, y + clip],
|
||||||
|
[x - clip + VoxelTexture.voxelSize, y - clip + VoxelTexture.voxelSize]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VoxelTexture
|
||||||
|
Loading…
Reference in New Issue
Block a user