mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2024-12-27 03:18:59 +08:00
Added UI option for choosing voxeliser algorithm
This commit is contained in:
parent
d6cf5db3d2
commit
16488c260f
@ -10,6 +10,8 @@ import { VoxelMesh, VoxelMeshParams } from './voxel_mesh';
|
|||||||
import { BlockMesh, BlockMeshParams } from './block_mesh';
|
import { BlockMesh, BlockMeshParams } from './block_mesh';
|
||||||
import { TextureFiltering } from './texture';
|
import { TextureFiltering } from './texture';
|
||||||
import { RayVoxeliser } from './voxelisers/ray-voxeliser';
|
import { RayVoxeliser } from './voxelisers/ray-voxeliser';
|
||||||
|
import { IVoxeliser } from './voxelisers/base-voxeliser';
|
||||||
|
import { NormalCorrectedRayVoxeliser } from './voxelisers/normal-corrected-ray-voxeliser';
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export enum ActionReturnType {
|
export enum ActionReturnType {
|
||||||
@ -170,7 +172,8 @@ export class AppContext {
|
|||||||
ambientOcclusionEnabled: uiElements.ambientOcclusion.getCachedValue() === 'on',
|
ambientOcclusionEnabled: uiElements.ambientOcclusion.getCachedValue() === 'on',
|
||||||
};
|
};
|
||||||
|
|
||||||
this._loadedVoxelMesh = new RayVoxeliser().voxelise(this._loadedMesh, voxelMeshParams);
|
const voxeliser: IVoxeliser = (uiElements.voxeliser.getCachedValue() === 'raybased' ? new RayVoxeliser() : new NormalCorrectedRayVoxeliser());
|
||||||
|
this._loadedVoxelMesh = voxeliser.voxelise(this._loadedMesh, voxelMeshParams);
|
||||||
Renderer.Get.useVoxelMesh(this._loadedVoxelMesh);
|
Renderer.Get.useVoxelMesh(this._loadedVoxelMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
src/ray.ts
56
src/ray.ts
@ -1,5 +1,5 @@
|
|||||||
import { Vector3 } from './vector';
|
import { Vector3 } from './vector';
|
||||||
import { ASSERT, Bounds } from './util';
|
import { ASSERT } from './util';
|
||||||
|
|
||||||
const EPSILON = 0.0000001;
|
const EPSILON = 0.0000001;
|
||||||
|
|
||||||
@ -27,60 +27,6 @@ export interface Ray {
|
|||||||
axis: Axes
|
axis: Axes
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateRays(v0: Vector3, v1: Vector3, v2: Vector3, offset: Vector3): Array<Ray> {
|
|
||||||
const bounds: Bounds = new Bounds(
|
|
||||||
new Vector3(
|
|
||||||
Math.ceil(Math.min(v0.x, v1.x, v2.x)),
|
|
||||||
Math.ceil(Math.min(v0.y, v1.y, v2.y)),
|
|
||||||
Math.ceil(Math.min(v0.z, v1.z, v2.z)),
|
|
||||||
),
|
|
||||||
new Vector3(
|
|
||||||
Math.floor(Math.max(v0.x, v1.x, v2.x)),
|
|
||||||
Math.floor(Math.max(v0.y, v1.y, v2.y)),
|
|
||||||
Math.floor(Math.max(v0.z, v1.z, v2.z)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
const rayList: Array<Ray> = [];
|
|
||||||
traverseX(rayList, bounds, offset);
|
|
||||||
traverseY(rayList, bounds, offset);
|
|
||||||
traverseZ(rayList, bounds, offset);
|
|
||||||
return rayList;
|
|
||||||
}
|
|
||||||
|
|
||||||
function traverseX(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
|
||||||
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
|
|
||||||
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
|
|
||||||
rayList.push({
|
|
||||||
origin: new Vector3(bounds.min.x - 1, y, z),
|
|
||||||
axis: Axes.x,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function traverseY(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
|
||||||
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
|
|
||||||
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
|
|
||||||
rayList.push({
|
|
||||||
origin: new Vector3(x, bounds.min.y - 1, z),
|
|
||||||
axis: Axes.y,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function traverseZ(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
|
||||||
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
|
|
||||||
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
|
|
||||||
rayList.push({
|
|
||||||
origin: new Vector3(x, y, bounds.min.z - 1),
|
|
||||||
axis: Axes.z,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) {
|
export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) {
|
||||||
const edge1 = Vector3.sub(v1, v0);
|
const edge1 = Vector3.sub(v1, v0);
|
||||||
const edge2 = Vector3.sub(v2, v0);
|
const edge2 = Vector3.sub(v2, v0);
|
||||||
|
@ -58,6 +58,10 @@ export class UI {
|
|||||||
label: 'Build',
|
label: 'Build',
|
||||||
elements: {
|
elements: {
|
||||||
'height': new SliderElement('Desired height', 3, 320, 0, 80),
|
'height': new SliderElement('Desired height', 3, 320, 0, 80),
|
||||||
|
'voxeliser': new ComboBoxElement('Algorithm', [
|
||||||
|
{ id: 'raybased', displayText: 'Ray-based' },
|
||||||
|
{ id: 'normalcorrectedraybased', displayText: 'NCRB (beta)' },
|
||||||
|
]),
|
||||||
'ambientOcclusion': new ComboBoxElement('Ambient occlusion', [
|
'ambientOcclusion': new ComboBoxElement('Ambient occlusion', [
|
||||||
{ id: 'on', displayText: 'On (recommended)' },
|
{ id: 'on', displayText: 'On (recommended)' },
|
||||||
{ id: 'off', displayText: 'Off (faster)' },
|
{ id: 'off', displayText: 'Off (faster)' },
|
||||||
@ -71,7 +75,7 @@ export class UI {
|
|||||||
{ id: 'nearest', displayText: 'Nearest (faster)' },
|
{ id: 'nearest', displayText: 'Nearest (faster)' },
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
elementsOrder: ['height', 'ambientOcclusion', 'multisampleColouring', 'textureFiltering'],
|
elementsOrder: ['height', 'voxeliser', 'ambientOcclusion', 'multisampleColouring', 'textureFiltering'],
|
||||||
submitButton: new ButtonElement('Voxelise mesh', () => {
|
submitButton: new ButtonElement('Voxelise mesh', () => {
|
||||||
this._appContext.do(Action.Voxelise);
|
this._appContext.do(Action.Voxelise);
|
||||||
}),
|
}),
|
||||||
|
179
src/voxelisers/normal-corrected-ray-voxeliser.ts
Normal file
179
src/voxelisers/normal-corrected-ray-voxeliser.ts
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import { VoxelMeshParams, VoxelMesh } from '../voxel_mesh';
|
||||||
|
import { AppConfig } from '../config';
|
||||||
|
import { Mesh } from '../mesh';
|
||||||
|
import { Axes, Ray, rayIntersectTriangle } from '../ray';
|
||||||
|
import { Triangle, UVTriangle } from '../triangle';
|
||||||
|
import { Bounds, RGB, UV } from '../util';
|
||||||
|
import { Vector3 } from '../vector';
|
||||||
|
import { IVoxeliser } from './base-voxeliser';
|
||||||
|
import { DebugGeometryTemplates } from '../geometry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This voxeliser works by projecting rays onto each triangle
|
||||||
|
* on each of the principle angles and testing for intersections
|
||||||
|
*/
|
||||||
|
export class NormalCorrectedRayVoxeliser extends IVoxeliser {
|
||||||
|
private _mesh?: Mesh;
|
||||||
|
private _voxelMesh?: VoxelMesh;
|
||||||
|
private _voxelMeshParams?: VoxelMeshParams;
|
||||||
|
private _scale!: number;
|
||||||
|
private _size!: Vector3;
|
||||||
|
private _offset!: Vector3;
|
||||||
|
|
||||||
|
public override voxelise(mesh: Mesh, voxelMeshParams: VoxelMeshParams): VoxelMesh {
|
||||||
|
this._mesh = mesh;
|
||||||
|
this._voxelMesh = new VoxelMesh(mesh, voxelMeshParams);
|
||||||
|
this._voxelMeshParams = voxelMeshParams;
|
||||||
|
|
||||||
|
this._scale = (voxelMeshParams.desiredHeight) / Mesh.desiredHeight;
|
||||||
|
const useMesh = mesh.copy();
|
||||||
|
|
||||||
|
useMesh.scaleMesh(this._scale);
|
||||||
|
const bounds = useMesh.getBounds();
|
||||||
|
this._size = Vector3.sub(bounds.max, bounds.min);
|
||||||
|
this._offset =new Vector3(
|
||||||
|
this._size.x % 2 < 0.001 ? 0.5 : 0.0,
|
||||||
|
this._size.y % 2 < 0.001 ? 0.5 : 0.0,
|
||||||
|
this._size.z % 2 < 0.001 ? 0.5 : 0.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
|
||||||
|
const uvTriangle = useMesh.getUVTriangle(triIndex);
|
||||||
|
const normals = useMesh.getNormals(triIndex);
|
||||||
|
const material = useMesh.getMaterialByTriangle(triIndex);
|
||||||
|
this._voxeliseTri(uvTriangle, material, normals);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._voxelMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3}) {
|
||||||
|
const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2,
|
||||||
|
this._offset,
|
||||||
|
);
|
||||||
|
|
||||||
|
rayList.forEach((ray) => {
|
||||||
|
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
|
||||||
|
if (intersection) {
|
||||||
|
const intersectionWorld = Vector3.divScalar(intersection, this._scale);
|
||||||
|
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.cross(
|
||||||
|
intersectionWorld,
|
||||||
|
0.1,
|
||||||
|
RGB.magenta,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Move transition away from normal
|
||||||
|
const norm = normals.v0.normalise();
|
||||||
|
intersection.sub(Vector3.mulScalar(norm, 0.5));
|
||||||
|
// Correct size parity
|
||||||
|
intersection.add(this._offset);
|
||||||
|
|
||||||
|
let voxelPosition: Vector3;
|
||||||
|
switch (ray.axis) {
|
||||||
|
case Axes.x:
|
||||||
|
voxelPosition = new Vector3(Math.round(intersection.x), intersection.y, intersection.z);
|
||||||
|
break;
|
||||||
|
case Axes.y:
|
||||||
|
voxelPosition = new Vector3(intersection.x, Math.round(intersection.y), intersection.z);
|
||||||
|
break;
|
||||||
|
case Axes.z:
|
||||||
|
voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
voxelPosition.round();
|
||||||
|
|
||||||
|
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.arrow(
|
||||||
|
intersectionWorld,
|
||||||
|
Vector3.divScalar(voxelPosition, this._scale),
|
||||||
|
RGB.magenta,
|
||||||
|
));
|
||||||
|
|
||||||
|
let voxelColour: RGB;
|
||||||
|
if (this._voxelMeshParams!.useMultisampleColouring) {
|
||||||
|
const samples: RGB[] = [];
|
||||||
|
for (let i = 0; i < AppConfig.MULTISAMPLE_COUNT; ++i) {
|
||||||
|
const samplePosition = Vector3.add(voxelPosition, Vector3.random().addScalar(-0.5));
|
||||||
|
samples.push(this._getVoxelColour(triangle, materialName, samplePosition));
|
||||||
|
}
|
||||||
|
voxelColour = RGB.averageFrom(samples);
|
||||||
|
} else {
|
||||||
|
voxelColour = this._getVoxelColour(triangle, materialName, voxelPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._voxelMesh!.addVoxel(voxelPosition, voxelColour);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getVoxelColour(triangle: UVTriangle, materialName: string, location: Vector3): RGB {
|
||||||
|
const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
|
||||||
|
const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
|
||||||
|
const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
|
||||||
|
const total = area01 + area12 + area20;
|
||||||
|
|
||||||
|
const w0 = area12 / total;
|
||||||
|
const w1 = area20 / total;
|
||||||
|
const w2 = area01 / total;
|
||||||
|
|
||||||
|
const uv = new UV(
|
||||||
|
triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
|
||||||
|
triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this._mesh!.sampleMaterial(materialName, uv, this._voxelMeshParams!.textureFiltering);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3, offset: Vector3): Array<Ray> {
|
||||||
|
const bounds: Bounds = new Bounds(
|
||||||
|
new Vector3(
|
||||||
|
Math.ceil(Math.min(v0.x, v1.x, v2.x)),
|
||||||
|
Math.ceil(Math.min(v0.y, v1.y, v2.y)),
|
||||||
|
Math.ceil(Math.min(v0.z, v1.z, v2.z)),
|
||||||
|
),
|
||||||
|
new Vector3(
|
||||||
|
Math.floor(Math.max(v0.x, v1.x, v2.x)),
|
||||||
|
Math.floor(Math.max(v0.y, v1.y, v2.y)),
|
||||||
|
Math.floor(Math.max(v0.z, v1.z, v2.z)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const rayList: Array<Ray> = [];
|
||||||
|
this._traverseX(rayList, bounds, offset);
|
||||||
|
this._traverseY(rayList, bounds, offset);
|
||||||
|
this._traverseZ(rayList, bounds, offset);
|
||||||
|
return rayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseX(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
||||||
|
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
|
||||||
|
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(bounds.min.x - 1, y, z),
|
||||||
|
axis: Axes.x,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseY(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
||||||
|
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
|
||||||
|
for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(x, bounds.min.y - 1, z),
|
||||||
|
axis: Axes.y,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseZ(rayList: Array<Ray>, bounds: Bounds, offset: Vector3) {
|
||||||
|
for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
|
||||||
|
for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(x, y, bounds.min.z - 1),
|
||||||
|
axis: Axes.z,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import { VoxelMeshParams, VoxelMesh } from '../voxel_mesh';
|
import { VoxelMeshParams, VoxelMesh } from '../voxel_mesh';
|
||||||
import { AppConfig } from '../config';
|
import { AppConfig } from '../config';
|
||||||
import { Mesh } from '../mesh';
|
import { Mesh } from '../mesh';
|
||||||
import { Axes, generateRays, rayIntersectTriangle } from '../ray';
|
import { Axes, Ray, rayIntersectTriangle } from '../ray';
|
||||||
import { Triangle, UVTriangle } from '../triangle';
|
import { Triangle, UVTriangle } from '../triangle';
|
||||||
import { RGB, UV } from '../util';
|
import { Bounds, RGB, UV } from '../util';
|
||||||
import { Vector3 } from '../vector';
|
import { Vector3 } from '../vector';
|
||||||
import { IVoxeliser } from './base-voxeliser';
|
import { IVoxeliser } from './base-voxeliser';
|
||||||
import { DebugGeometryTemplates } from '../geometry';
|
import { DebugGeometryTemplates } from '../geometry';
|
||||||
@ -17,7 +17,6 @@ export class RayVoxeliser extends IVoxeliser {
|
|||||||
private _voxelMesh?: VoxelMesh;
|
private _voxelMesh?: VoxelMesh;
|
||||||
private _voxelMeshParams?: VoxelMeshParams;
|
private _voxelMeshParams?: VoxelMeshParams;
|
||||||
private _scale!: number;
|
private _scale!: number;
|
||||||
private _size!: Vector3;
|
|
||||||
private _offset!: Vector3;
|
private _offset!: Vector3;
|
||||||
|
|
||||||
public override voxelise(mesh: Mesh, voxelMeshParams: VoxelMeshParams): VoxelMesh {
|
public override voxelise(mesh: Mesh, voxelMeshParams: VoxelMeshParams): VoxelMesh {
|
||||||
@ -25,49 +24,40 @@ export class RayVoxeliser extends IVoxeliser {
|
|||||||
this._voxelMesh = new VoxelMesh(mesh, voxelMeshParams);
|
this._voxelMesh = new VoxelMesh(mesh, voxelMeshParams);
|
||||||
this._voxelMeshParams = voxelMeshParams;
|
this._voxelMeshParams = voxelMeshParams;
|
||||||
|
|
||||||
this._scale = (voxelMeshParams.desiredHeight) / Mesh.desiredHeight;
|
this._scale = (voxelMeshParams.desiredHeight - 1) / Mesh.desiredHeight;
|
||||||
|
this._offset = (voxelMeshParams.desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
|
||||||
const useMesh = mesh.copy();
|
const useMesh = mesh.copy();
|
||||||
|
|
||||||
useMesh.scaleMesh(this._scale);
|
useMesh.scaleMesh(this._scale);
|
||||||
const bounds = useMesh.getBounds();
|
useMesh.translateMesh(this._offset);
|
||||||
this._size = Vector3.sub(bounds.max, bounds.min);
|
|
||||||
this._offset =new Vector3(
|
|
||||||
this._size.x % 2 < 0.001 ? 0.5 : 0.0,
|
|
||||||
this._size.y % 2 < 0.001 ? 0.5 : 0.0,
|
|
||||||
this._size.z % 2 < 0.001 ? 0.5 : 0.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
|
for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
|
||||||
const uvTriangle = useMesh.getUVTriangle(triIndex);
|
const uvTriangle = useMesh.getUVTriangle(triIndex);
|
||||||
const normals = useMesh.getNormals(triIndex);
|
|
||||||
const material = useMesh.getMaterialByTriangle(triIndex);
|
const material = useMesh.getMaterialByTriangle(triIndex);
|
||||||
this._voxeliseTri(uvTriangle, material, normals);
|
this._voxeliseTri(uvTriangle, material);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._voxelMesh;
|
return this._voxelMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3}) {
|
private _voxeliseTri(triangle: UVTriangle, materialName: string) {
|
||||||
const rayList = generateRays(triangle.v0, triangle.v1, triangle.v2,
|
const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2);
|
||||||
this._offset,
|
|
||||||
);
|
|
||||||
|
|
||||||
rayList.forEach((ray) => {
|
rayList.forEach((ray) => {
|
||||||
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
|
const rayOriginWorld = Vector3.divScalar(ray.origin, this._scale).sub(this._offset);
|
||||||
if (intersection) {
|
|
||||||
const intersectionWorld = Vector3.divScalar(intersection, this._scale);
|
|
||||||
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.cross(
|
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.cross(
|
||||||
intersectionWorld,
|
rayOriginWorld,
|
||||||
0.1,
|
0.1,
|
||||||
RGB.magenta,
|
ray.axis === Axes.x ? RGB.red : (ray.axis === Axes.y ? RGB.green : RGB.blue),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Move transition away from normal
|
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
|
||||||
const norm = normals.v0.normalise();
|
if (intersection) {
|
||||||
intersection.sub(Vector3.mulScalar(norm, 0.5));
|
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.arrow(
|
||||||
// Correct size parity
|
rayOriginWorld,
|
||||||
intersection.add(this._offset);
|
Vector3.divScalar(intersection, this._scale).sub(this._offset),
|
||||||
|
ray.axis === Axes.x ? RGB.red : (ray.axis === Axes.y ? RGB.green : RGB.blue),
|
||||||
|
));
|
||||||
let voxelPosition: Vector3;
|
let voxelPosition: Vector3;
|
||||||
switch (ray.axis) {
|
switch (ray.axis) {
|
||||||
case Axes.x:
|
case Axes.x:
|
||||||
@ -80,13 +70,6 @@ export class RayVoxeliser extends IVoxeliser {
|
|||||||
voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
|
voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
voxelPosition.round();
|
|
||||||
|
|
||||||
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.arrow(
|
|
||||||
intersectionWorld,
|
|
||||||
Vector3.divScalar(voxelPosition, this._scale),
|
|
||||||
RGB.magenta,
|
|
||||||
));
|
|
||||||
|
|
||||||
let voxelColour: RGB;
|
let voxelColour: RGB;
|
||||||
if (this._voxelMeshParams!.useMultisampleColouring) {
|
if (this._voxelMeshParams!.useMultisampleColouring) {
|
||||||
@ -122,4 +105,58 @@ export class RayVoxeliser extends IVoxeliser {
|
|||||||
|
|
||||||
return this._mesh!.sampleMaterial(materialName, uv, this._voxelMeshParams!.textureFiltering);
|
return this._mesh!.sampleMaterial(materialName, uv, this._voxelMeshParams!.textureFiltering);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3): Array<Ray> {
|
||||||
|
const bounds: Bounds = new Bounds(
|
||||||
|
new Vector3(
|
||||||
|
Math.floor(Math.min(v0.x, v1.x, v2.x)),
|
||||||
|
Math.floor(Math.min(v0.y, v1.y, v2.y)),
|
||||||
|
Math.floor(Math.min(v0.z, v1.z, v2.z)),
|
||||||
|
),
|
||||||
|
new Vector3(
|
||||||
|
Math.ceil(Math.max(v0.x, v1.x, v2.x)),
|
||||||
|
Math.ceil(Math.max(v0.y, v1.y, v2.y)),
|
||||||
|
Math.ceil(Math.max(v0.z, v1.z, v2.z)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const rayList: Array<Ray> = [];
|
||||||
|
this._traverseX(rayList, bounds);
|
||||||
|
this._traverseY(rayList, bounds);
|
||||||
|
this._traverseZ(rayList, bounds);
|
||||||
|
return rayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseX(rayList: Array<Ray>, bounds: Bounds) {
|
||||||
|
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
|
||||||
|
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(bounds.min.x - 1, y, z),
|
||||||
|
axis: Axes.x,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseY(rayList: Array<Ray>, bounds: Bounds) {
|
||||||
|
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
|
||||||
|
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(x, bounds.min.y - 1, z),
|
||||||
|
axis: Axes.y,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _traverseZ(rayList: Array<Ray>, bounds: Bounds) {
|
||||||
|
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
|
||||||
|
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
|
||||||
|
rayList.push({
|
||||||
|
origin: new Vector3(x, y, bounds.min.z - 1),
|
||||||
|
axis: Axes.z,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user