Added grid, fixed #29

This commit is contained in:
Lucas Dower 2022-03-07 18:45:06 +00:00
parent c4a6f1d79f
commit 6ef0e89d49
16 changed files with 363 additions and 49 deletions

View File

@ -1,8 +1,9 @@
uniform mat4 u_worldViewProjection;
uniform sampler2D u_texture;
uniform float u_voxelSize;
uniform vec3 u_translate;
attribute vec4 position;
attribute vec3 position;
attribute vec3 normal;
attribute vec4 occlusion;
attribute vec2 texcoord;
@ -21,5 +22,5 @@ void main() {
v_blockTexcoord = blockTexcoord;
v_lighting = dot(light, abs(normal));
gl_Position = u_worldViewProjection * vec4(position.xyz * u_voxelSize, 1.0);
gl_Position = u_worldViewProjection * vec4((position.xyz + vec3(0.5)) * u_voxelSize + u_translate, 1.0);
}

View File

@ -0,0 +1,7 @@
precision mediump float;
varying vec3 v_colour;
void main() {
gl_FragColor = vec4(v_colour, 1.0);
}

11
shaders/debug_vertex.vs Normal file
View File

@ -0,0 +1,11 @@
uniform mat4 u_worldViewProjection;
attribute vec3 position;
attribute vec3 colour;
varying vec3 v_colour;
void main() {
v_colour = colour;
gl_Position = u_worldViewProjection * vec4(position, 1.0);
}

View File

@ -2,8 +2,9 @@ uniform vec3 u_lightWorldPos;
uniform mat4 u_worldViewProjection;
uniform mat4 u_worldInverseTranspose;
uniform vec3 u_fillColour;
uniform vec3 u_translate;
attribute vec4 position;
attribute vec3 position;
attribute vec2 texcoord;
attribute vec3 normal;
@ -14,5 +15,5 @@ void main() {
lighting = (clamp(lighting, 0.0, 1.0) * 0.66) + 0.33;
v_lighting = lighting;
gl_Position = u_worldViewProjection * vec4(position.xyz, 1.0);
gl_Position = u_worldViewProjection * vec4(position + u_translate, 1.0);
}

View File

@ -1,8 +1,9 @@
uniform vec3 u_lightWorldPos;
uniform mat4 u_worldViewProjection;
uniform mat4 u_worldInverseTranspose;
uniform vec3 u_translate;
attribute vec4 position;
attribute vec3 position;
attribute vec2 texcoord;
attribute vec3 normal;
@ -16,5 +17,5 @@ void main() {
lighting = (clamp(lighting, 0.0, 1.0) * 0.66) + 0.33;
v_lighting = lighting;
gl_Position = u_worldViewProjection * vec4(position.xyz, 1.0);
gl_Position = u_worldViewProjection * vec4(position + u_translate, 1.0);
}

View File

@ -1,7 +1,8 @@
uniform mat4 u_worldViewProjection;
uniform float u_voxelSize;
uniform vec3 u_translate;
attribute vec4 position;
attribute vec3 position;
attribute vec3 normal;
attribute vec3 colour;
attribute vec4 occlusion;
@ -20,5 +21,5 @@ void main() {
v_texcoord = texcoord;
v_colour = colour;
gl_Position = u_worldViewProjection * vec4(position.xyz * u_voxelSize, 1.0);
gl_Position = u_worldViewProjection * vec4((position.xyz + vec3(0.5)) * u_voxelSize + u_translate, 1.0);
}

View File

@ -1,6 +1,5 @@
import { Renderer } from './renderer';
import { ASSERT } from './util';
import { AppConfig } from './config';
import * as twgl from 'twgl.js';
@ -19,7 +18,7 @@ interface BottomlessAttributeData {
data: Array<number>
}
export interface VoxelData {
export interface AttributeData {
indices: Uint32Array
custom: {
[name: string]: Array<number>
@ -53,13 +52,7 @@ export class RenderBuffer {
this._getNewBuffer();
}
public add(data: VoxelData) {
ASSERT(!this._compiled);
if (AppConfig.DEBUG_ENABLED) {
// this._checkDataMatchesAttributes(data);
}
public add(data: AttributeData) {
const mappedIndicesToAdd = new Array<number>(data.indices.length);
let maxMapped = -1;
data.indices.forEach((index, i) => {
@ -140,7 +133,7 @@ export class RenderBuffer {
}
}
private _checkDataMatchesAttributes(data: VoxelData) {
private _checkDataMatchesAttributes(data: AttributeData) {
if (!('indices' in data)) {
throw Error('Given data does not have indices data');
}

View File

@ -15,10 +15,12 @@ export class ArcballCamera {
private actualDistance = 18.0;
private actualAzimuth = -1.0;
private actualElevation = 1.3;
private actualHeight = 0.0;
private targetDistance: number;
private targetAzimuth: number;
private targetElevation: number;
public targetHeight: number;
private readonly target: v3.Vec3 = [0, 0, 0];
private readonly up: v3.Vec3 = [0, 1, 0];
@ -33,7 +35,6 @@ export class ArcballCamera {
private gl: WebGLRenderingContext;
private static _instance: ArcballCamera;
public static get Get() {
return this._instance || (this._instance = new this());
}
@ -48,6 +49,7 @@ export class ArcballCamera {
this.targetDistance = this.actualDistance;
this.targetAzimuth = this.actualAzimuth;
this.targetElevation = this.actualElevation;
this.targetHeight = this.actualHeight;
}
public updateCamera() {
@ -68,6 +70,7 @@ export class ArcballCamera {
this.actualDistance += (this.targetDistance - this.actualDistance ) * this.cameraSmoothing;
this.actualAzimuth += (this.targetAzimuth - this.actualAzimuth ) * this.cameraSmoothing;
this.actualElevation += (this.targetElevation - this.actualElevation) * this.cameraSmoothing;
this.actualHeight += (this.targetHeight - this.actualHeight ) * this.cameraSmoothing;
this.eye = [
this.actualDistance * Math.cos(this.actualAzimuth) * -Math.sin(this.actualElevation),
@ -104,7 +107,7 @@ export class ArcballCamera {
}
public getCameraMatrix() {
return m4.lookAt(this.eye, this.target, this.up);
return m4.lookAt(v3.add(this.eye, [0, this.actualHeight, 0]), v3.add(this.target, [0, this.actualHeight, 0]), this.up);
}
public getViewMatrix() {

View File

@ -1,12 +1,13 @@
import * as twgl from 'twgl.js';
import { UVTriangle } from './triangle';
import { Vector3 } from './vector';
import { VoxelData } from './buffer';
import { AttributeData } from './buffer';
import { Bounds, RGB } from './util';
export class GeometryTemplates {
private static readonly _default_cube = twgl.primitives.createCubeVertices(1.0);
static getTriangleBufferData(triangle: UVTriangle): VoxelData {
static getTriangleBufferData(triangle: UVTriangle): AttributeData {
const n = triangle.getNormal();
return {
@ -33,8 +34,8 @@ export class GeometryTemplates {
};
}
static getBoxBufferData(centre: Vector3): VoxelData {
const cube: VoxelData = {
static getBoxBufferData(centre: Vector3): AttributeData {
const cube: AttributeData = {
custom: {
position: new Array<number>(72),
texcoord: new Array<number>(48),
@ -57,3 +58,86 @@ export class GeometryTemplates {
return cube;
}
}
export class DebugGeometryTemplates {
public static cross(centre: Vector3, radius: number, colour: RGB) {
return {
indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
custom: {
position: [
centre.x + radius, centre.y, centre.z,
centre.x - radius, centre.y, centre.z,
centre.x, centre.y + radius, centre.z,
centre.x, centre.y - radius, centre.z,
centre.x, centre.y, centre.z + radius,
centre.x, centre.y, centre.z - radius,
],
colour: [
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
],
},
};
}
public static line(start: Vector3, end: Vector3, colour: RGB) {
return {
indices: new Uint32Array([0, 1]),
custom: {
position: [
start.x, start.y, start.z,
end.x, end.y, end.z,
],
colour: [
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
],
},
};
}
public static bounds(bounds: Bounds, colour: RGB, translate: Vector3 = new Vector3(0, 0, 0)) {
return {
indices: new Uint32Array([
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7,
]),
custom: {
position: [
bounds.min.x + translate.x, bounds.min.y + translate.y, bounds.min.z + translate.z,
bounds.max.x + translate.x, bounds.min.y + translate.y, bounds.min.z + translate.z,
bounds.max.x + translate.x, bounds.min.y + translate.y, bounds.max.z + translate.z,
bounds.min.x + translate.x, bounds.min.y + translate.y, bounds.max.z + translate.z,
bounds.min.x + translate.x, bounds.max.y + translate.y, bounds.min.z + translate.z,
bounds.max.x + translate.x, bounds.max.y + translate.y, bounds.min.z + translate.z,
bounds.max.x + translate.x, bounds.max.y + translate.y, bounds.max.z + translate.z,
bounds.min.x + translate.x, bounds.max.y + translate.y, bounds.max.z + translate.z,
],
colour: [
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
colour.r, colour.g, colour.b,
],
},
};
}
}

View File

@ -236,7 +236,39 @@ export class Mesh extends Warnable {
*/
public copy(): Mesh {
return new Mesh(this.vertices, this.uvs, this.tris, this.materials);
const newVertices = new Array<Vector3>(this.vertices.length);
for (let i = 0; i < this.vertices.length; ++i) {
newVertices[i] = this.vertices[i].copy();
}
const newUVs = new Array<UV>(this.uvs.length);
for (let i = 0; i < this.uvs.length; ++i) {
newUVs[i] = this.uvs[i].copy();
}
const newTris = new Array<Tri>(this.tris.length);
for (let i = 0; i < this.tris.length; ++i) {
// FIXME: Replace
newTris[i] = JSON.parse(JSON.stringify(this.tris[i]));
}
const materials: { [materialName: string]: (SolidMaterial | TexturedMaterial) } = {}; // JSON.parse(JSON.stringify(this.materials));
for (const materialName in this.materials) {
const material = this.materials[materialName];
if (material.type === MaterialType.solid) {
materials[materialName] = {
type: MaterialType.solid,
colour: material.colour.copy(),
};
} else {
materials[materialName] = {
type: MaterialType.textured,
path: material.path,
};
};
}
return new Mesh(newVertices, newUVs, newTris, materials);
}
public getTriangleCount(): number {

View File

@ -2,10 +2,10 @@ import { Vector3 } from './vector';
import { ArcballCamera } from './camera';
import { ShaderManager } from './shaders';
import { RenderBuffer } from './buffer';
import { GeometryTemplates } from './geometry';
import { DebugGeometryTemplates, GeometryTemplates } from './geometry';
import { Mesh, SolidMaterial, TexturedMaterial, MaterialType } from './mesh';
import { BlockAtlas } from './block_atlas';
import { ASSERT, LOG, RGB } from './util';
import { LOG, RGB } from './util';
import { VoxelMesh } from './voxel_mesh';
import { BlockMesh } from './block_mesh';
@ -20,18 +20,30 @@ enum MeshType {
}
/* eslint-enable */
interface DebugSettings {
axis: boolean;
bounds: boolean;
grid?: DebugGridSettings;
}
interface DebugGridSettings {
size: number,
}
export class Renderer {
public _gl: WebGLRenderingContext;
private _backgroundColour = new RGB(0.1, 0.1, 0.1);
private _backgroundColour = new RGB(0.125, 0.125, 0.125);
private _atlasTexture?: WebGLTexture;
private _occlusionNeighboursIndices!: Array<Array<Array<number>>>; // Ew
private _meshToUse: MeshType = MeshType.None;
private _voxelSize: number = 1.0;
private _translate: Vector3;
public _voxelBuffer: RenderBuffer;
private _blockBuffer: RenderBuffer;
private _debugBuffer: RenderBuffer;
private _materialBuffers: Array<{
buffer: RenderBuffer,
material: (SolidMaterial | (TexturedMaterial & { texture: WebGLTexture }))
@ -43,13 +55,23 @@ export class Renderer {
}
private constructor() {
this._gl = (<HTMLCanvasElement>document.getElementById('canvas')).getContext('webgl')!;
this._gl = (<HTMLCanvasElement>document.getElementById('canvas')).getContext('webgl', {
alpha: false,
})!;
twgl.addExtensionsToContext(this._gl);
this._setupOcclusions();
this._translate = new Vector3(0, 0, 0);
this._voxelBuffer = new RenderBuffer([]);
this._blockBuffer = new RenderBuffer([]);
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: 0.25,
},
});
this._materialBuffers = [];
}
@ -60,6 +82,8 @@ export class Renderer {
public draw() {
this._setupScene();
this._drawDebug();
switch (this._meshToUse) {
case MeshType.TriangleMesh:
this._drawMesh();
@ -124,6 +148,18 @@ export class Renderer {
});
}
}
this._translate = new Vector3(0, mesh.getBounds().getDimensions().y/2, 0);
ArcballCamera.Get.targetHeight = this._translate.y;
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: 0.25,
},
});
// this._debugBuffer.add(DebugGeometryTemplates.bounds(mesh.getBounds(), RGB.white, this._translate));
this._meshToUse = MeshType.TriangleMesh;
}
@ -132,25 +168,54 @@ export class Renderer {
LOG('Using voxel mesh');
LOG(voxelMesh);
this._voxelBuffer = voxelMesh.createBuffer();
this._meshToUse = MeshType.VoxelMesh;
this._voxelSize = voxelMesh?.getVoxelSize();
this._translate = new Vector3(0, voxelMesh.getBounds().getDimensions().y/2 * voxelMesh.getVoxelSize(), 0);
ArcballCamera.Get.targetHeight = this._translate.y;
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: voxelMesh.getVoxelSize(),
},
});
// this._debugBuffer.add(DebugGeometryTemplates.bounds(voxelMesh.getMesh().getBounds(), RGB.white, this._translate));
this._meshToUse = MeshType.VoxelMesh;
}
public useBlockMesh(blockMesh: BlockMesh) {
LOG('Using block mesh');
LOG(blockMesh);
this._blockBuffer = blockMesh.createBuffer();
this._meshToUse = MeshType.BlockMesh;
this._voxelSize = blockMesh.getVoxelMesh().getVoxelSize();
this._atlasTexture = twgl.createTexture(this._gl, {
src: BlockAtlas.Get.getAtlasTexturePath(),
mag: this._gl.NEAREST,
});
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: 0.25,
},
});
// this._debugBuffer.add(DebugGeometryTemplates.bounds(blockMesh.getVoxelMesh().getMesh().getBounds(), RGB.white, this._translate));
this._meshToUse = MeshType.BlockMesh;
}
// /////////////////////////////////////////////////////////////////////////
private _drawDebug() {
this._drawBuffer(this._gl.LINES, this._debugBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
});
}
private _drawMesh() {
for (const materialBuffer of this._materialBuffers) {
if (materialBuffer.material.type === MaterialType.textured) {
@ -159,6 +224,7 @@ export class Renderer {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
u_texture: materialBuffer.material.texture,
u_translate: this._translate.toArray(),
});
} else {
this._drawRegister(materialBuffer.buffer, ShaderManager.Get.solidTriProgram, {
@ -166,6 +232,7 @@ export class Renderer {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
u_fillColour: materialBuffer.material.colour.toArray(),
u_translate: this._translate.toArray(),
});
}
}
@ -175,6 +242,7 @@ export class Renderer {
this._drawRegister(this._voxelBuffer, ShaderManager.Get.voxelProgram, {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
u_voxelSize: this._voxelSize,
u_translate: this._translate.toArray(),
});
}
@ -184,6 +252,7 @@ export class Renderer {
u_texture: this._atlasTexture,
u_voxelSize: this._voxelSize,
u_atlasSize: BlockAtlas.Get.getAtlasSize(),
u_translate: this._translate.toArray(),
});
}
@ -279,4 +348,84 @@ export class Renderer {
twgl.setUniforms(shader, uniforms);
this._gl.drawElements(drawMode, buffer.numElements, this._gl.UNSIGNED_INT, 0);
}
private _setupDebugBuffer(settings: DebugSettings): RenderBuffer {
const buffer = new RenderBuffer([
{ name: 'position', numComponents: 3 },
{ name: 'colour', numComponents: 3 },
]);
const gridRadius = 9.5;
const gridColourMinor = new RGB(0.15, 0.15, 0.15);
const gridColourMajor = new RGB(0.3, 0.3, 0.3);
if (settings.axis) {
buffer.add(DebugGeometryTemplates.line(
new Vector3(-gridRadius, 0, 0),
new Vector3(gridRadius, 0, 0),
(new RGB(0.44, 0.64, 0.11)),
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(0, 0, -gridRadius),
new Vector3(0, 0, gridRadius),
new RGB(0.96, 0.21, 0.32)),
);
}
if (settings.bounds) {
buffer.add(DebugGeometryTemplates.line(
new Vector3(-gridRadius, 0, -gridRadius),
new Vector3(gridRadius, 0, -gridRadius),
gridColourMajor,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(gridRadius, 0, -gridRadius),
new Vector3(gridRadius, 0, gridRadius),
gridColourMajor,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(gridRadius, 0, gridRadius),
new Vector3(-gridRadius, 0, gridRadius),
gridColourMajor,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(-gridRadius, 0, gridRadius),
new Vector3(-gridRadius, 0, -gridRadius),
gridColourMajor,
));
}
if (settings.grid) {
let count = 1;
for (let i = 0; i < gridRadius; i += settings.grid.size) {
buffer.add(DebugGeometryTemplates.line(
new Vector3(i, 0, gridRadius),
new Vector3(i, 0, -gridRadius),
count % 10 === 0 ? gridColourMajor : gridColourMinor,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(gridRadius, 0, i),
new Vector3(-gridRadius, 0, i),
count % 10 === 0 ? gridColourMajor : gridColourMinor,
));
++count;
}
count = 1;
for (let i = 0; i > -gridRadius; i -= settings.grid.size) {
buffer.add(DebugGeometryTemplates.line(
new Vector3(i, 0, gridRadius),
new Vector3(i, 0, -gridRadius),
count % 10 === 0 ? gridColourMajor : gridColourMinor,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(gridRadius, 0, i),
new Vector3(-gridRadius, 0, i),
count % 10 === 0 ? gridColourMajor : gridColourMinor,
));
++count;
}
}
return buffer;
}
}

View File

@ -8,6 +8,7 @@ export class ShaderManager {
public readonly solidTriProgram: twgl.ProgramInfo;
public readonly voxelProgram: twgl.ProgramInfo;
public readonly blockProgram: twgl.ProgramInfo;
public readonly debugProgram: twgl.ProgramInfo;
private static _instance: ShaderManager;
public static get Get() {
@ -32,6 +33,10 @@ export class ShaderManager {
const blockVertexShader = this._getShader('block_vertex.vs');
const blockFragmentShader = this._getShader('block_fragment.fs');
this.blockProgram = twgl.createProgramInfo(gl, [blockVertexShader, blockFragmentShader]);
const debugVertexShader = this._getShader('debug_vertex.vs');
const debugFragmentShader = this._getShader('debug_fragment.fs');
this.debugProgram = twgl.createProgramInfo(gl, [debugVertexShader, debugFragmentShader]);
}
private _getShader(filename: string) {

View File

@ -82,11 +82,12 @@ export class SliderElement extends LabelledElement<number> {
const xOffset = mouseEvent.clientX - elementBar.getBoundingClientRect().x;
const width = element.clientWidth;
const norm = clamp(xOffset / width, 0.0, 1.0);
this._value = (norm * (this._max - this._min)) + this._min;
elementBar.style.width = `${norm * 100}%`;
elementValue.innerHTML = this._value.toFixed(this._decimals);
const value = (norm * (this._max - this._min)) + this._min;
const displayValue = value.toFixed(this._decimals);
elementValue.innerHTML = displayValue;
this._value = parseFloat(displayValue);
}
protected _onEnabledChanged() {

View File

@ -48,7 +48,7 @@ export class UI {
'build': {
label: 'Build',
elements: {
'height': new SliderElement('Desired height', 1, 320, 0, 80),
'height': new SliderElement('Desired height', 5, 320, 0, 80),
'ambientOcclusion': new ComboBoxElement('Ambient occlusion', [
{ id: 'on', displayText: 'On (recommended)' },
{ id: 'off', displayText: 'Off (faster)' },
@ -220,11 +220,9 @@ export class UI {
LOG('enabling', action);
// TODO: Remove once Simplify has been implemented
/*
if (action === Action.Simplify) {
action = Action.Voxelise;
}
*/
const group = this._getActionGroup(action);
for (const compName in group.elements) {
group.elements[compName].setEnabled(true);

View File

@ -13,6 +13,10 @@ export class UV {
this.u = u;
this.v = v;
}
public copy() {
return new UV(this.u, this.v);
}
}
/* eslint-disable */
@ -75,6 +79,10 @@ export class RGB {
return new RGB(1.0, 1.0, 1.0);
}
public static get yellow(): RGB {
return new RGB(1.0, 1.0, 0.0);
}
public static get black(): RGB {
return new RGB(0.0, 0.0, 0.0);
}
@ -86,6 +94,10 @@ export class RGB {
public toVector3(): Vector3 {
return new Vector3(this.r, this.g, this.b);
}
public copy() {
return new RGB(this.r, this.g, this.b);
}
}
/**
@ -129,6 +141,10 @@ export class Bounds {
const extents = Vector3.sub(this._max, this._min).divScalar(2);
return Vector3.add(this.min, extents);
}
public getDimensions() {
return Vector3.sub(this._max, this._min);
}
}
export function ASSERT(condition: any, errorMessage = 'Assertion Failed'): asserts condition {

View File

@ -1,4 +1,4 @@
import { RenderBuffer, VoxelData } from './buffer';
import { RenderBuffer, AttributeData } from './buffer';
import { AppConfig } from './config';
import { GeometryTemplates } from './geometry';
import { HashMap } from './hash_map';
@ -28,11 +28,13 @@ export class VoxelMesh {
private _voxelMeshParams: VoxelMeshParams;
private _voxelSize: number;
private _desiredHeight: number;
private _voxels: Voxel[];
private _voxelsHash: HashMap<Vector3, number>;
private _loadedTextures: { [materialName: string]: Texture };
private _bounds: Bounds;
public static createFromMesh(mesh: Mesh, voxelMeshParams: VoxelMeshParams) {
const voxelMesh = new VoxelMesh(mesh, voxelMeshParams);
voxelMesh._voxelise();
@ -46,6 +48,7 @@ export class VoxelMesh {
this._voxelMeshParams = voxelMeshParams;
this._voxelSize = 8.0 / Math.round(voxelMeshParams.desiredHeight);
this._desiredHeight = this._voxelMeshParams.desiredHeight;
this._voxels = [];
this._voxelsHash = new HashMap(2048);
this._loadedTextures = {};
@ -60,29 +63,37 @@ export class VoxelMesh {
return this._voxelsHash.has(pos);
}
public getMesh() {
return this._mesh;
}
private _voxelise() {
LOG('Voxelising');
this._mesh.tris.forEach((tri, index) => {
const material = this._mesh.materials[tri.material];
const scale = (this._desiredHeight - 1) / Mesh.desiredHeight;
const offset = (this._desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
const useMesh = this._mesh.copy();
for (let i = 0; i < useMesh.vertices.length; ++i) {
useMesh.vertices[i].mulScalar(scale).add(offset);
}
useMesh.tris.forEach((tri, index) => {
const material = useMesh.materials[tri.material];
if (material.type == MaterialType.textured) {
if (!(tri.material in this._loadedTextures)) {
this._loadedTextures[tri.material] = new Texture(material.path);
}
}
const uvTriangle = this._mesh.getUVTriangle(index);
const uvTriangle = useMesh.getUVTriangle(index);
this._voxeliseTri(uvTriangle, material, tri.material);
});
}
private _voxeliseTri(triangle: UVTriangle, material: (SolidMaterial | TexturedMaterial), materialName: string) {
const v0Scaled = Vector3.divScalar(triangle.v0, this._voxelSize);
const v1Scaled = Vector3.divScalar(triangle.v1, this._voxelSize);
const v2Scaled = Vector3.divScalar(triangle.v2, this._voxelSize);
const rayList = generateRays(v0Scaled, v1Scaled, v2Scaled);
const rayList = generateRays(triangle.v0, triangle.v1, triangle.v2);
rayList.forEach((ray) => {
const intersection = rayIntersectTriangle(ray, v0Scaled, v1Scaled, v2Scaled);
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
if (intersection) {
let voxelPosition: Vector3;
switch (ray.axis) {
@ -185,7 +196,7 @@ export class VoxelMesh {
occlusions = OcclusionManager.Get.getBlankOcclusions();
}
const data: VoxelData = GeometryTemplates.getBoxBufferData(voxel.position);
const data: AttributeData = GeometryTemplates.getBoxBufferData(voxel.position);
data.custom.occlusion = occlusions;
data.custom.colour = [];