Added wireframe debug toggle

This commit is contained in:
Lucas Dower 2022-03-18 21:43:41 +00:00
parent 7b87bfbe61
commit 9cfc34a38a
7 changed files with 222 additions and 197 deletions

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-squares-diagonal" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00abfb" fill="none" stroke-linecap="round" stroke-linejoin="round" id="wireframe-svg">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="8" y="8" width="12" height="12" rx="2" />
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
<path d="M8.586 19.414l10.827 -10.827" />
</svg>

After

Width:  |  Height:  |  Size: 485 B

View File

@ -5,6 +5,7 @@ export enum EAppEvent {
onModelActiveChanged,
onModelAvailableChanged,
onGridEnabledChanged,
onWireframeEnabledChanged,
}
/* eslint-enable */

View File

@ -3,6 +3,7 @@ import { UVTriangle } from './triangle';
import { Vector3 } from './vector';
import { AttributeData, RenderBuffer } from './buffer';
import { Bounds, RGB } from './util';
import { Mesh } from './mesh';
export class GeometryTemplates {
private static readonly _default_cube = twgl.primitives.createCubeVertices(1.0);
@ -163,7 +164,7 @@ export class DebugGeometryTemplates {
};
}
public static cone(tipCentre: Vector3, tipHeight: number, normal: Vector3, radius: number, colour: RGB, quarterSteps: number) {
public static cone(tipCentre: Vector3, tipHeight: number, normal: Vector3, radius: number, colour: RGB, quarterSteps: number): AttributeData {
const indices = [];
const positions = [];
const colours = [];
@ -198,6 +199,124 @@ export class DebugGeometryTemplates {
};
}
public static grid(axes: boolean, bounds: boolean, gridSize: number): 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 (axes) {
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.cone(
new Vector3(gridRadius, 0, 0),
0.5,
new Vector3(1, 0, 0),
0.1,
new RGB(0.44, 0.64, 0.11),
8,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(0, 0, -gridRadius),
new Vector3(0, 0, gridRadius),
new RGB(0.96, 0.21, 0.32)),
);
buffer.add(DebugGeometryTemplates.cone(
new Vector3(0, 0, gridRadius),
0.5,
new Vector3(0, 0, 1),
0.1,
new RGB(0.96, 0.21, 0.32),
8,
));
}
if (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,
));
}
let count = 1;
for (let i = 0; i < gridRadius; i += gridSize) {
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 -= gridSize) {
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;
}
public static meshWireframe(mesh: Mesh, colour: RGB): RenderBuffer {
const buffer = new RenderBuffer([
{ name: 'position', numComponents: 3 },
{ name: 'colour', numComponents: 3 },
]);
for (const tri of mesh.tris) {
const v0 = mesh.vertices[tri.iX];
const v1 = mesh.vertices[tri.iY];
const v2 = mesh.vertices[tri.iZ];
buffer.add(DebugGeometryTemplates.line(
v0, v1, colour,
));
buffer.add(DebugGeometryTemplates.line(
v1, v2, colour,
));
buffer.add(DebugGeometryTemplates.line(
v2, v0, colour,
));
}
return buffer;
}
static _generateCirclePoints(centre: Vector3, normal: Vector3, radius: number, steps: number): Vector3[] {
normal = normal.copy().normalise();

View File

@ -5,7 +5,7 @@ import { RenderBuffer } from './buffer';
import { DebugGeometryTemplates, GeometryTemplates } from './geometry';
import { Mesh, SolidMaterial, TexturedMaterial, MaterialType } from './mesh';
import { BlockAtlas } from './block_atlas';
import { LOG, RGB } from './util';
import { ASSERT, LOG, RGB } from './util';
import { VoxelMesh } from './voxel_mesh';
import { BlockMesh } from './block_mesh';
@ -21,15 +21,13 @@ export enum MeshType {
}
/* eslint-enable */
interface DebugSettings {
axis: boolean;
bounds: boolean;
grid?: DebugGridSettings;
}
interface DebugGridSettings {
size: number,
/* eslint-disable */
enum EDebugBufferComponents {
Grid,
Wireframe,
Bounds,
}
/* eslint-enable */
export class Renderer {
public _gl: WebGLRenderingContext;
@ -40,7 +38,6 @@ export class Renderer {
private _meshToUse: MeshType = MeshType.None;
private _voxelSize: number = 1.0;
private _translate: Vector3;
private _gridOffset: Vector3 = new Vector3(0, 0, 0);
private _modelsAvailable: number;
@ -51,9 +48,9 @@ export class Renderer {
}>;
public _voxelBuffer: RenderBuffer;
private _blockBuffer: RenderBuffer;
private _debugBuffer: RenderBuffer;
private _debugBuffers: { [meshType: string]: { [bufferComponent: string]: RenderBuffer } };
private _isGridEnabled: boolean;
private _isGridComponentEnabled: { [bufferComponent: string]: boolean };
private static _instance: Renderer;
public static get Get() {
@ -69,19 +66,19 @@ export class Renderer {
this._setupOcclusions();
this._modelsAvailable = 0;
this._translate = new Vector3(0, 0, 0);
this._materialBuffers = [];
this._voxelBuffer = new RenderBuffer([]);
this._blockBuffer = new RenderBuffer([]);
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: 0.25,
},
});
this._materialBuffers = [];
this._isGridEnabled = false;
this._debugBuffers = {};
this._debugBuffers[MeshType.None] = {};
this._debugBuffers[MeshType.TriangleMesh] = {};
this._debugBuffers[MeshType.VoxelMesh] = {};
this._debugBuffers[MeshType.BlockMesh] = {};
this._debugBuffers[MeshType.None][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(true, true, 0.25);
this._isGridComponentEnabled = {};
this._isGridComponentEnabled[EDebugBufferComponents.Grid] = false;
}
public update() {
@ -91,9 +88,7 @@ export class Renderer {
public draw() {
this._setupScene();
if (this._isGridEnabled) {
this._drawDebug();
}
this._drawDebug();
switch (this._meshToUse) {
case MeshType.TriangleMesh:
@ -110,17 +105,16 @@ export class Renderer {
// /////////////////////////////////////////////////////////////////////////
private static _faceNormals = [
new Vector3(1, 0, 0), new Vector3(-1, 0, 0),
new Vector3(0, 1, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, 1), new Vector3(0, 0, -1),
];
// /////////////////////////////////////////////////////////////////////////
public toggleIsGridEnabled() {
this._isGridEnabled = !this._isGridEnabled;
EventManager.Get.broadcast(EAppEvent.onGridEnabledChanged, this._isGridEnabled);
const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Grid];
this._isGridComponentEnabled[EDebugBufferComponents.Grid] = isEnabled;
EventManager.Get.broadcast(EAppEvent.onGridEnabledChanged, isEnabled);
}
public toggleIsWireframeEnabled() {
const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Wireframe];
this._isGridComponentEnabled[EDebugBufferComponents.Wireframe] = isEnabled;
EventManager.Get.broadcast(EAppEvent.onWireframeEnabledChanged, isEnabled);
}
public useMesh(mesh: Mesh) {
@ -169,16 +163,8 @@ export class Renderer {
}
}
this._translate = new Vector3(0, mesh.getBounds().getDimensions().y/2, 0);
this._debugBuffer = this._setupDebugBuffer({
axis: true,
bounds: true,
grid: {
size: 0.25,
},
});
// this._debugBuffer.add(DebugGeometryTemplates.bounds(mesh.getBounds(), RGB.white, this._translate));
this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(true, true, 0.25);
this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Wireframe] = DebugGeometryTemplates.meshWireframe(mesh, new RGB(0.18, 0.52, 0.89));
this._modelsAvailable = 1;
this.setModelToUse(MeshType.TriangleMesh);
@ -203,14 +189,7 @@ export class Renderer {
dimensions.z % 2 === 0 ? 0.5 : 0,
);
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._debugBuffers[MeshType.VoxelMesh][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(true, true, voxelMesh.getVoxelSize());
this._modelsAvailable = 2;
this.setModelToUse(MeshType.VoxelMesh);
@ -231,14 +210,7 @@ export class Renderer {
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._debugBuffers[MeshType.BlockMesh][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(true, true, blockMesh.getVoxelMesh().getVoxelSize());
this._modelsAvailable = 3;
this.setModelToUse(MeshType.BlockMesh);
@ -249,9 +221,18 @@ export class Renderer {
// /////////////////////////////////////////////////////////////////////////
private _drawDebug() {
this._drawBuffer(this._gl.LINES, this._debugBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
});
const debugComponents = [EDebugBufferComponents.Grid, EDebugBufferComponents.Wireframe];
for (const debugComp of debugComponents) {
if (this._isGridComponentEnabled[debugComp]) {
ASSERT(this._debugBuffers[this._meshToUse]);
const buffer = this._debugBuffers[this._meshToUse][debugComp];
if (buffer) {
this._drawBuffer(this._gl.LINES, buffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
});
}
}
}
}
private _drawMesh() {
@ -392,100 +373,4 @@ 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.cone(
new Vector3(gridRadius, 0, 0),
0.5,
new Vector3(1, 0, 0),
0.1,
new RGB(0.44, 0.64, 0.11),
8,
));
buffer.add(DebugGeometryTemplates.line(
new Vector3(0, 0, -gridRadius),
new Vector3(0, 0, gridRadius),
new RGB(0.96, 0.21, 0.32)),
);
buffer.add(DebugGeometryTemplates.cone(
new Vector3(0, 0, gridRadius),
0.5,
new Vector3(0, 0, 1),
0.1,
new RGB(0.96, 0.21, 0.32),
8,
));
}
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

@ -12,7 +12,10 @@ export class ToolbarItemElement {
private _isActive: boolean;
private _onClick: () => void;
public constructor(iconName: string, onClick: () => void, _enableChangedEvent?: EAppEvent, _enableChangedDelegate?: (...args: any[]) => boolean, _activeChangedEvent?: EAppEvent, _activeChangedDelegate?: (...args: any[]) => boolean) {
public constructor(iconName: string, onClick: () => void,
_activeChangedEvent?: EAppEvent, _activeChangedDelegate?: (...args: any[]) => boolean,
_enableChangedEvent?: EAppEvent, _enableChangedDelegate?: (...args: any[]) => boolean,
) {
this._id = getRandomID();
this._iconName = iconName;
this._iconPath = path.join(__dirname, '../../../resources/static/', iconName + '.svg');
@ -20,21 +23,23 @@ export class ToolbarItemElement {
this._isActive = false;
this._onClick = onClick;
// Enabled/Disabled Event
if (_enableChangedEvent !== undefined && _enableChangedDelegate) {
EventManager.Get.add(_enableChangedEvent, (...args: any[]) => {
const isActive = _enableChangedDelegate(args);
this.setActive(isActive);
});
}
if (_activeChangedEvent !== undefined && _activeChangedDelegate) {
EventManager.Get.add(_activeChangedEvent, (...args: any[]) => {
const isEnabled = _activeChangedDelegate(args);
const isEnabled = _enableChangedDelegate(args);
this.setEnabled(isEnabled);
});
} else {
this._isEnabled = true;
}
// Active/Inactive Event
if (_activeChangedEvent !== undefined && _activeChangedDelegate) {
EventManager.Get.add(_activeChangedEvent, (...args: any[]) => {
const isActive = _activeChangedDelegate(args);
this.setActive(isActive);
});
}
}
public generateHTML() {
@ -68,49 +73,37 @@ export class ToolbarItemElement {
}
});
this._onEnabledChanged();
this._onActiveChanged();
this._updateElements();
}
private _onEnabledChanged() {
private _updateElements() {
const element = document.getElementById(this._id) as HTMLDivElement;
const svgElement = document.getElementById(this._iconName + '-svg') as HTMLDivElement;
ASSERT(element !== null && svgElement !== null);
element.classList.remove('toolbar-item-disabled');
element.classList.remove('toolbar-item-active');
svgElement.classList.remove('icon-disabled');
svgElement.classList.remove('icon-active');
if (this._isEnabled) {
element.classList.remove('toolbar-item-disabled');
svgElement.classList.remove('icon-disabled');
if (this._isActive) {
element.classList.add('toolbar-item-active');
svgElement.classList.add('icon-active');
}
} else {
element.classList.add('toolbar-item-disabled');
svgElement.classList.add('icon-disabled');
}
}
private _onActiveChanged() {
const element = document.getElementById(this._id) as HTMLDivElement;
const svgElement = document.getElementById(this._iconName + '-svg') as HTMLDivElement;
ASSERT(element !== null && svgElement !== null);
element.classList.remove('toolbar-item-active');
svgElement.classList.remove('icon-active');
if (this._isActive) {
element.classList.add('toolbar-item-active');
svgElement.classList.add('icon-active');
} else {
element.classList.remove('toolbar-item-active');
svgElement.classList.remove('icon-active');
}
}
public setEnabled(isEnabled: boolean) {
this._isEnabled = isEnabled;
this._onEnabledChanged();
this._updateElements();
}
public setActive(isActive: boolean) {
this._isActive = isActive;
this._onActiveChanged();
this._updateElements();
}
}

View File

@ -119,7 +119,7 @@ export class UI {
elements: {
'mesh': new ToolbarItemElement('mesh', () => {
Renderer.Get.setModelToUse(MeshType.TriangleMesh);
},
},
EAppEvent.onModelActiveChanged, (...args: any[]) => {
const modelUsed = args[0][0][0] as MeshType;
return modelUsed === MeshType.TriangleMesh;
@ -186,12 +186,21 @@ export class UI {
const isEnabled = args[0][0][0] as boolean;
return isEnabled;
}),
'wireframe': new ToolbarItemElement('wireframe', () => {
Renderer.Get.toggleIsWireframeEnabled();
}, EAppEvent.onWireframeEnabledChanged, (...args: any[]) => {
const isEnabled = args[0][0][0] as boolean;
return isEnabled;
}, EAppEvent.onModelActiveChanged, (...args: any[]) => {
const modelUsed = args[0][0][0] as MeshType;
return modelUsed === MeshType.TriangleMesh;
}),
/*
'bounds': new ToolbarItemElement('bounds', () => {
}),
*/
},
elementsOrder: ['grid'], // ['grid', 'bounds'],
elementsOrder: ['grid', 'wireframe'], // ['grid', 'bounds'],
},
},
groupsOrder: ['viewmode', 'zoom', 'debug'],

View File

@ -83,6 +83,18 @@ export class RGB {
return new RGB(1.0, 1.0, 0.0);
}
public static get red(): RGB {
return new RGB(1.0, 0.0, 0.0);
}
public static get green(): RGB {
return new RGB(0.0, 1.0, 0.0);
}
public static get blue(): RGB {
return new RGB(0.0, 0.0, 1.0);
}
public static get black(): RGB {
return new RGB(0.0, 0.0, 0.0);
}