mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2025-01-24 13:04:36 +08:00
Added grid, fixed #29
This commit is contained in:
parent
c4a6f1d79f
commit
6ef0e89d49
@ -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);
|
||||
}
|
||||
|
7
shaders/debug_fragment.fs
Normal file
7
shaders/debug_fragment.fs
Normal 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
11
shaders/debug_vertex.vs
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
34
src/mesh.ts
34
src/mesh.ts
@ -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 {
|
||||
|
163
src/renderer.ts
163
src/renderer.ts
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
16
src/util.ts
16
src/util.ts
@ -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 {
|
||||
|
@ -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 = [];
|
||||
|
Loading…
Reference in New Issue
Block a user