forked from mirror/ObjToSchematic
Optimised block assigning
This commit is contained in:
parent
8549901a43
commit
8619f9fa18
@ -46,7 +46,6 @@
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"expand-vertex-data": "^1.1.2",
|
||||
"jpeg-js": "^0.4.3",
|
||||
"mesh-simplify": "^2.0.0",
|
||||
"mtltojs": "^0.2.1",
|
||||
"obj-file-parser": "^0.5.3",
|
||||
"pngjs": "^6.0.0",
|
||||
|
@ -2,11 +2,12 @@ import { BasicBlockAssigner, OrderedDitheringBlockAssigner } from './block_assig
|
||||
import { Voxel, VoxelMesh } from './voxel_mesh';
|
||||
import { BlockInfo } from './block_atlas';
|
||||
import { CustomError, LOG } from './util';
|
||||
import { RenderBuffer, VoxelData } from './buffer';
|
||||
import { RenderBuffer, VoxelData, Attribute } from './buffer';
|
||||
import { OcclusionManager } from './occlusion';
|
||||
import { GeometryTemplates } from './geometry';
|
||||
import { AppConfig } from './config';
|
||||
import { Vector3 } from './vector';
|
||||
import { Renderer } from './renderer';
|
||||
|
||||
interface Block {
|
||||
voxel: Voxel;
|
||||
@ -65,59 +66,21 @@ export class BlockMesh {
|
||||
}
|
||||
|
||||
public createBuffer(ambientOcclusionEnabled: boolean) {
|
||||
const buffer = new RenderBuffer([
|
||||
{ name: 'position', numComponents: 3},
|
||||
{ name: 'normal', numComponents: 3 },
|
||||
{ name: 'occlusion', numComponents: 4 },
|
||||
{ name: 'texcoord', numComponents: 2 },
|
||||
{ name: 'blockTexcoord', numComponents: 2 },
|
||||
]);
|
||||
// const buffer = this.getVoxelMesh().createBuffer(ambientOcclusionEnabled);
|
||||
const buffer = Renderer.Get._voxelBuffer.copy();
|
||||
|
||||
const blockTexcoords: number[] = [];
|
||||
for (const block of this._blocks) {
|
||||
// Each vertex of a face needs the occlusion data for the other 3 vertices
|
||||
// in it's face, not just itself. Also flatten occlusion data.
|
||||
let occlusions: number[];
|
||||
if (ambientOcclusionEnabled) {
|
||||
occlusions = OcclusionManager.Get.getOcclusions(block.voxel.position, this.getVoxelMesh());
|
||||
} else {
|
||||
occlusions = OcclusionManager.Get.getBlankOcclusions();
|
||||
}
|
||||
|
||||
const data: VoxelData = GeometryTemplates.getBoxBufferData(block.voxel.position);
|
||||
data.custom.occlusion = occlusions;
|
||||
|
||||
// Assign the textures to each face
|
||||
data.custom.blockTexcoord = [];
|
||||
const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
|
||||
for (const face of faceOrder) {
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
const texcoord = block.blockInfo.faces[face].texcoord;
|
||||
data.custom.blockTexcoord.push(texcoord.u, texcoord.v);
|
||||
blockTexcoords.push(texcoord.u, texcoord.v);
|
||||
}
|
||||
}
|
||||
|
||||
const faceNormals = OcclusionManager.Get.getFaceNormals();
|
||||
if (AppConfig.FACE_CULLING) {
|
||||
// TODO: Optmise, enabling FACE_CULLING is slower than not bothering
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
if (!this.getVoxelMesh().isVoxelAt(Vector3.add(block.voxel.position, faceNormals[i]))) {
|
||||
buffer.add({
|
||||
custom: {
|
||||
position: data.custom.position.slice(i * 12, (i+1) * 12),
|
||||
occlusion: data.custom.occlusion.slice(i * 16, (i+1) * 16),
|
||||
normal: data.custom.normal.slice(i * 12, (i+1) * 12),
|
||||
texcoord: data.custom.texcoord.slice(i * 8, (i+1) * 8),
|
||||
colour: data.custom.colour.slice(i * 12, (i+1) * 12),
|
||||
blockTexcoord: data.custom.blockTexcoord.slice(i * 8, (i+1) * 8),
|
||||
},
|
||||
indices: data.indices.slice(0, 6),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer.add(data);
|
||||
}
|
||||
}
|
||||
buffer.attachNewAttribute({ name: 'blockTexcoord', numComponents: 2 }, blockTexcoords);
|
||||
buffer.removeAttribute('colour');
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Renderer } from './renderer';
|
||||
import { ASSERT, LOG } from './util';
|
||||
import { AppConfig } from './config';
|
||||
|
||||
import * as twgl from 'twgl.js';
|
||||
import { ASSERT } from './util';
|
||||
|
||||
interface Attribute {
|
||||
export interface Attribute {
|
||||
name: string,
|
||||
numComponents: number
|
||||
}
|
||||
@ -32,13 +33,11 @@ export class RenderBuffer {
|
||||
};
|
||||
private _buffer!: BottomlessBufferData;
|
||||
private _attributes: {[name: string]: Attribute};
|
||||
private _maxIndex: number = 0;
|
||||
private _compiled: boolean = false;
|
||||
private _sanityCheck: boolean = false;
|
||||
private _maxIndex: number;
|
||||
private _compiled: boolean;
|
||||
private _needsCompiling: boolean;
|
||||
|
||||
public constructor(attributes: Array<Attribute>) {
|
||||
this._compiled = false;
|
||||
|
||||
this._attributes = {};
|
||||
for (const attr of attributes) {
|
||||
this._attributes[attr.name] = {
|
||||
@ -46,15 +45,19 @@ export class RenderBuffer {
|
||||
numComponents: attr.numComponents,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this._needsCompiling = false;
|
||||
this._compiled = false;
|
||||
this._maxIndex = 0;
|
||||
|
||||
this._getNewBuffer();
|
||||
}
|
||||
|
||||
public add(data: VoxelData) {
|
||||
if (this._sanityCheck) {
|
||||
this._checkDataMatchesAttributes(data);
|
||||
ASSERT(!this._compiled);
|
||||
|
||||
if (AppConfig.DEBUG_ENABLED) {
|
||||
// this._checkDataMatchesAttributes(data);
|
||||
}
|
||||
|
||||
const mappedIndicesToAdd = new Array<number>(data.indices.length);
|
||||
@ -70,14 +73,27 @@ export class RenderBuffer {
|
||||
for (const attr in this._attributes) {
|
||||
this._buffer[attr].data.push(...data.custom[attr]);
|
||||
}
|
||||
|
||||
this._needsCompiling = true;
|
||||
}
|
||||
|
||||
public attachNewAttribute(data: VoxelData) {
|
||||
|
||||
public attachNewAttribute(attribute: Attribute, data: Array<number>) {
|
||||
ASSERT(this._buffer[attribute.name] === undefined, 'Attribute already exists in buffer');
|
||||
ASSERT(this._attributes[attribute.name] === undefined, 'Attribute already exists in attributes');
|
||||
const expectedDataLength = this._maxIndex * attribute.numComponents;
|
||||
ASSERT(data.length === expectedDataLength, `Data length expected to be ${expectedDataLength}, got ${data.length}`);
|
||||
this._buffer[attribute.name] = {
|
||||
numComponents: attribute.numComponents,
|
||||
data: data,
|
||||
};
|
||||
this._attributes[attribute.name] = attribute;
|
||||
this._needsCompiling = true;
|
||||
}
|
||||
|
||||
public removeAttribute(attribute: string) {
|
||||
|
||||
public removeAttribute(attributeName: string) {
|
||||
delete this._buffer[attributeName];
|
||||
delete this._attributes[attributeName];
|
||||
this._needsCompiling = true;
|
||||
}
|
||||
|
||||
public getWebGLBuffer() {
|
||||
@ -87,7 +103,7 @@ export class RenderBuffer {
|
||||
}
|
||||
|
||||
private _compile() {
|
||||
if (this._compiled) {
|
||||
if (this._compiled && !this._needsCompiling) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -109,6 +125,7 @@ export class RenderBuffer {
|
||||
};
|
||||
|
||||
this._compiled = true;
|
||||
this._needsCompiling = false;
|
||||
}
|
||||
|
||||
private _getNewBuffer() {
|
||||
@ -142,4 +159,29 @@ export class RenderBuffer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public copy(): RenderBuffer {
|
||||
const copiedBuffer = new RenderBuffer([]);
|
||||
|
||||
copiedBuffer._buffer = {
|
||||
indices: {
|
||||
numComponents: this._buffer.indices.numComponents,
|
||||
data: Array.from(this._buffer.indices.data),
|
||||
},
|
||||
};
|
||||
for (const key in this._buffer) {
|
||||
if (key !== 'indices') {
|
||||
copiedBuffer._buffer[key] = {
|
||||
numComponents: this._buffer[key].numComponents,
|
||||
data: Array.from(this._buffer[key].data),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
copiedBuffer._attributes = JSON.parse(JSON.stringify(this._attributes));
|
||||
copiedBuffer._maxIndex = this._maxIndex;
|
||||
copiedBuffer._compiled = false;
|
||||
copiedBuffer._needsCompiling = true;
|
||||
return copiedBuffer;
|
||||
}
|
||||
}
|
||||
|
@ -10,4 +10,6 @@ export namespace AppConfig {
|
||||
export const ASSERTIONS_ENABLED = true;
|
||||
|
||||
export const FACE_CULLING = false;
|
||||
|
||||
export const DEBUG_ENABLED = true;
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ export class Renderer {
|
||||
private _meshToUse: MeshType = MeshType.None;
|
||||
private _voxelSize: number = 1.0;
|
||||
|
||||
private _buffer: RenderBuffer;
|
||||
public _voxelBuffer: RenderBuffer;
|
||||
private _blockBuffer: RenderBuffer;
|
||||
private _materialBuffers: Array<{
|
||||
buffer: RenderBuffer,
|
||||
material: (SolidMaterial | (TexturedMaterial & { texture: WebGLTexture }))
|
||||
@ -48,7 +49,8 @@ export class Renderer {
|
||||
|
||||
this._setupOcclusions();
|
||||
|
||||
this._buffer = new RenderBuffer([]);
|
||||
this._voxelBuffer = new RenderBuffer([]);
|
||||
this._blockBuffer = new RenderBuffer([]);
|
||||
this._materialBuffers = [];
|
||||
|
||||
this._atlasTexture = twgl.createTexture(this._gl, {
|
||||
@ -130,7 +132,7 @@ export class Renderer {
|
||||
public useVoxelMesh(voxelMesh: VoxelMesh, ambientOcclusionEnabled: boolean) {
|
||||
LOG('Using voxel mesh');
|
||||
LOG(voxelMesh);
|
||||
this._buffer = voxelMesh.createBuffer(ambientOcclusionEnabled);
|
||||
this._voxelBuffer = voxelMesh.createBuffer(ambientOcclusionEnabled);
|
||||
this._meshToUse = MeshType.VoxelMesh;
|
||||
this._voxelSize = voxelMesh?.getVoxelSize();
|
||||
}
|
||||
@ -138,7 +140,7 @@ export class Renderer {
|
||||
public useBlockMesh(blockMesh: BlockMesh, ambientOcclusionEnabled: boolean) {
|
||||
LOG('Using block mesh');
|
||||
LOG(blockMesh);
|
||||
this._buffer = blockMesh.createBuffer(ambientOcclusionEnabled);
|
||||
this._blockBuffer = blockMesh.createBuffer(ambientOcclusionEnabled);
|
||||
this._meshToUse = MeshType.BlockMesh;
|
||||
this._voxelSize = blockMesh.getVoxelMesh().getVoxelSize();
|
||||
}
|
||||
@ -166,14 +168,14 @@ export class Renderer {
|
||||
}
|
||||
|
||||
private _drawVoxelMesh() {
|
||||
this._drawRegister(this._buffer, ShaderManager.Get.voxelProgram, {
|
||||
this._drawRegister(this._voxelBuffer, ShaderManager.Get.voxelProgram, {
|
||||
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
|
||||
u_voxelSize: this._voxelSize,
|
||||
});
|
||||
}
|
||||
|
||||
private _drawBlockMesh() {
|
||||
this._drawRegister(this._buffer, ShaderManager.Get.blockProgram, {
|
||||
this._drawRegister(this._blockBuffer, ShaderManager.Get.blockProgram, {
|
||||
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
|
||||
u_texture: this._atlasTexture,
|
||||
u_voxelSize: this._voxelSize,
|
||||
|
Loading…
Reference in New Issue
Block a user