skycraft: optimize mesh generation
This commit is contained in:
parent
b0a39bb1ce
commit
e27151b796
@ -5,6 +5,7 @@ import {loadTexture, makeProgram} from '../gl';
|
||||
import {makeFace, makeBufferFromFaces} from '../geometry';
|
||||
import { loadStlModel } from './stl';
|
||||
import * as linalg from './linalg';
|
||||
import { memoize } from '../memoize';
|
||||
|
||||
const VSHADER = `
|
||||
attribute vec3 aPosition;
|
||||
@ -243,7 +244,7 @@ const CHUNKSIZE = 32;
|
||||
*
|
||||
* returns: a chunk
|
||||
*/
|
||||
function getChunk(seed, x, y, z) {
|
||||
function makeDirtBlock(seed, x, y, z) {
|
||||
// XXX: for now, return a premade chunk: a 24x24x24 cube of dirt
|
||||
// surrounded by 4 blocks of air all around
|
||||
const cs = CHUNKSIZE;
|
||||
@ -271,15 +272,83 @@ function getChunk(seed, x, y, z) {
|
||||
position: [-half, -half, -half],
|
||||
blocks,
|
||||
underground: false,
|
||||
seed,
|
||||
};
|
||||
}
|
||||
|
||||
function getBodyChunks(seed) {
|
||||
if (seed === 0) {
|
||||
return makeSun();
|
||||
function makeSunChunk(seed, i, j, k) {
|
||||
const cs = CHUNKSIZE;
|
||||
const radius = 42;
|
||||
if (Math.abs(cs * i) > radius
|
||||
|| Math.abs(cs * j) > radius
|
||||
|| Math.abs(cs * k) > radius) {
|
||||
return undefined;
|
||||
}
|
||||
const half = cs / 2;
|
||||
const blocks = new Array(cs**3);
|
||||
blocks.fill(BlockType.SUN);
|
||||
|
||||
let underground = true;
|
||||
|
||||
for (let x = 0; x < cs; x++) {
|
||||
for (let y = 0; y < cs; y++) {
|
||||
for (let z = 0; z < cs; z++) {
|
||||
const pos = [
|
||||
x + i * cs - half,
|
||||
y + j * cs - half,
|
||||
z + k * cs - half,
|
||||
];
|
||||
const idx = (
|
||||
z * cs * cs +
|
||||
y * cs +
|
||||
x
|
||||
);
|
||||
if (pos[0]**2 + pos[1]**2 + pos[2]**2 > radius**2) {
|
||||
blocks[idx] = BlockType.AIR;
|
||||
underground = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [getChunk(seed, 0, 0, 0)];
|
||||
return {
|
||||
position: [i * cs - half, j * cs - half, k * cs - half],
|
||||
layout: [i, j, k],
|
||||
blocks,
|
||||
seed,
|
||||
underground,
|
||||
};
|
||||
}
|
||||
|
||||
function _getChunk(seed, chunkX, chunkY, chunkZ) {
|
||||
if (seed === 0) {
|
||||
return makeSunChunk(seed, chunkX, chunkY, chunkZ);
|
||||
}
|
||||
if (chunkX === 0 && chunkY === 0 && chunkZ === 0) {
|
||||
return makeDirtBlock(seed); // x, y, z unused right now
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
const getChunk = memoize(_getChunk);
|
||||
|
||||
function getBodyChunks(seed) {
|
||||
const chunks = [];
|
||||
const toCheck = [[0, 0, 0]];
|
||||
while (toCheck.length > 0) {
|
||||
const [chunkX, chunkY, chunkZ] = toCheck.pop();
|
||||
const thisChunk = getChunk(seed, chunkX, chunkY, chunkZ);
|
||||
if (thisChunk === undefined || chunks.includes(thisChunk)) {
|
||||
continue;
|
||||
}
|
||||
chunks.push(thisChunk);
|
||||
toCheck.push([chunkX - 1, chunkY, chunkZ]);
|
||||
toCheck.push([chunkX + 1, chunkY, chunkZ]);
|
||||
toCheck.push([chunkX, chunkY - 1, chunkZ]);
|
||||
toCheck.push([chunkX, chunkY + 1, chunkZ]);
|
||||
toCheck.push([chunkX, chunkY, chunkZ - 1]);
|
||||
toCheck.push([chunkX, chunkY, chunkZ + 1]);
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function faceTexture(type, dir) {
|
||||
@ -320,6 +389,49 @@ function* makeChunkFaces(chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
function neighborChunk(dir) {
|
||||
const [chunkX, chunkY, chunkZ] = chunk.layout;
|
||||
if (chunk.neighbors === undefined) {
|
||||
chunk.neighbors = {};
|
||||
}
|
||||
if (!(dir in chunk.neighbors)) {
|
||||
if (dir === '-x') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX - 1, chunkY, chunkZ);
|
||||
} else if (dir === '+x') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX + 1, chunkY, chunkZ);
|
||||
} else if (dir === '-y') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX, chunkY - 1, chunkZ);
|
||||
} else if (dir === '+y') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX, chunkY + 1, chunkZ);
|
||||
} else if (dir === '-z') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX, chunkY, chunkZ - 1);
|
||||
} else if (dir === '+z') {
|
||||
chunk.neighbors[dir] = getChunk(chunk.seed, chunkX, chunkY, chunkZ + 1);
|
||||
}
|
||||
}
|
||||
return chunk.neighbors[dir];
|
||||
}
|
||||
|
||||
const neighborIndices = {
|
||||
'-x': (x, y, z) => z * cs * cs + y * cs + (cs - 1),
|
||||
'+x': (x, y, z) => z * cs * cs + y * cs + 0,
|
||||
'-y': (x, y, z) => z * cs * cs + (cs - 1) * cs + x,
|
||||
'+y': (x, y, z) => z * cs * cs + 0 * cs + x,
|
||||
'-z': (x, y, z) => (cs - 1) * cs * cs + y * cs + x,
|
||||
'+z': (x, y, z) => 0 * cs * cs + y * cs + x,
|
||||
};
|
||||
|
||||
function neighborBlock(dir, x, y, z) {
|
||||
const neighbor = neighborChunk(dir);
|
||||
let block;
|
||||
if (neighbor === undefined) {
|
||||
block = BlockType.AIR;
|
||||
} else {
|
||||
block = neighbor.blocks[neighborIndices[dir](x, y, z)];
|
||||
}
|
||||
return { dir, block };
|
||||
}
|
||||
|
||||
function* neighbors(x, y, z) {
|
||||
const idx = (
|
||||
z * cs * cs +
|
||||
@ -332,21 +444,15 @@ function* makeChunkFaces(chunk) {
|
||||
dir: '-x',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '-x',
|
||||
};
|
||||
yield neighborBlock('-x', x, y, z);
|
||||
}
|
||||
if (x < 31) {
|
||||
if (x < cs - 1) {
|
||||
yield {
|
||||
block: chunk.blocks[idx + 1],
|
||||
dir: '+x',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '+x',
|
||||
};
|
||||
yield neighborBlock('+x', x, y, z);
|
||||
}
|
||||
if (y > 0) {
|
||||
yield {
|
||||
@ -354,21 +460,15 @@ function* makeChunkFaces(chunk) {
|
||||
dir: '-y',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '-y',
|
||||
};
|
||||
yield neighborBlock('-y', x, y, z);
|
||||
}
|
||||
if (y < 31) {
|
||||
if (y < cs - 1) {
|
||||
yield {
|
||||
block: chunk.blocks[idx + cs],
|
||||
dir: '+y',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '+y',
|
||||
};
|
||||
yield neighborBlock('+y', x, y, z);
|
||||
}
|
||||
if (z > 0) {
|
||||
yield {
|
||||
@ -376,21 +476,15 @@ function* makeChunkFaces(chunk) {
|
||||
dir: '-z',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '-z',
|
||||
};
|
||||
yield neighborBlock('-z', x, y, z);
|
||||
}
|
||||
if (z < 31) {
|
||||
if (z < cs - 1) {
|
||||
yield {
|
||||
block: chunk.blocks[idx + cs * cs],
|
||||
dir: '+z',
|
||||
};
|
||||
} else {
|
||||
yield {
|
||||
block: BlockType.AIR,
|
||||
dir: '+z',
|
||||
};
|
||||
yield neighborBlock('+z', x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,59 +524,6 @@ function closeToPlanet(context) {
|
||||
return linalg.norm(relativePos) < 20;
|
||||
}
|
||||
|
||||
function makeSun(seed) {
|
||||
const radius = 7;
|
||||
const radiusChunks = Math.floor(radius / CHUNKSIZE);
|
||||
|
||||
const chunks = [];
|
||||
|
||||
function makeSunChunk(i, j, k) {
|
||||
const cs = CHUNKSIZE;
|
||||
const half = cs / 2;
|
||||
const blocks = new Array(cs**3);
|
||||
blocks.fill(BlockType.SUN);
|
||||
|
||||
let underground = true;
|
||||
|
||||
for (let x = 0; x < cs; x++) {
|
||||
for (let y = 0; y < cs; y++) {
|
||||
for (let z = 0; z < cs; z++) {
|
||||
const pos = [
|
||||
x + i * cs - half,
|
||||
y + j * cs - half,
|
||||
z + k * cs - half,
|
||||
];
|
||||
const idx = (
|
||||
z * cs * cs +
|
||||
y * cs +
|
||||
x
|
||||
);
|
||||
if (pos[0]**2 + pos[1]**2 + pos[2]**2 > radius**2) {
|
||||
blocks[idx] = BlockType.AIR;
|
||||
underground = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
position: [i * cs - half, j * cs - half, k * cs - half],
|
||||
blocks,
|
||||
underground,
|
||||
};
|
||||
}
|
||||
|
||||
for (let i = -radiusChunks; i <= radiusChunks; i++) {
|
||||
for (let j = -radiusChunks; j <= radiusChunks; j++) {
|
||||
for (let k = -radiusChunks; k <= radiusChunks; k++) {
|
||||
chunks.push(makeSunChunk(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function getBodyGeometry(seed) {
|
||||
const faces = getBodyChunks(seed)
|
||||
.filter(chunk => !chunk.underground)
|
||||
@ -1208,6 +1249,7 @@ async function main() {
|
||||
// [ ] huge planets
|
||||
// [x] lighting
|
||||
// [ ] better lighting
|
||||
// [x] optimize geometry generation
|
||||
|
||||
const modelPromise = loadStlModel('spaceship.stl');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user