Skip to content

Commit

Permalink
Optimised voxelisation
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasDower committed Oct 22, 2023
1 parent 70d4df2 commit 6e81858
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 54 deletions.
92 changes: 47 additions & 45 deletions Core/src/ots_voxel_mesh_converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { OtS_ReplaceMode, OtS_VoxelMesh } from './ots_voxel_mesh';
import { TAxis } from './util/type_util';
import { Vector3 } from './vector';
import { Triangle } from './triangle';
import { Axes, Ray, rayIntersectTriangle } from './ray';
import { rayIntersectTriangleFastX, rayIntersectTriangleFastY, rayIntersectTriangleFastZ } from './ray';
import { OtS_Colours, RGBA, RGBAUtil } from './colour';
import { OtS_Mesh, OtS_Triangle } from './ots_mesh';
import { UV } from './util';

export type OtS_VoxelMesh_ConverterConfig = {
constraintAxis: TAxis,
size: number,
multisampling: boolean,
multisampling?: number,
replaceMode: OtS_ReplaceMode,
}

Expand All @@ -21,7 +21,7 @@ export class OtS_VoxelMesh_Converter {
this._config = {
constraintAxis: 'y',
size: 80,
multisampling: true,
multisampling: 8,
replaceMode: 'average',
};
}
Expand Down Expand Up @@ -60,68 +60,70 @@ export class OtS_VoxelMesh_Converter {
bounds.min.floor();
bounds.max.ceil();

const ray: Ray = { axis: Axes.x, origin: new Vector3(0, 0, 0) };
const rayOrigin = new Vector3(0, 0, 0);

ray.origin.x = bounds.min.x - 1;
ray.axis = Axes.x;
rayOrigin.x = bounds.min.x - 1;
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
ray.origin.y = y;
rayOrigin.y = y;
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
ray.origin.z = z;
this._handleRay(ray, triangle, voxelMesh);
rayOrigin.z = z;
const intersection = rayIntersectTriangleFastX(rayOrigin, triangle);
if (intersection) {
this._handleRayHit(intersection, triangle, voxelMesh);
}
}
}

ray.origin.y = bounds.min.y - 1;
ray.axis = Axes.y;
rayOrigin.y = bounds.min.y - 1;
for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
ray.origin.z = z;
rayOrigin.z = z;
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
ray.origin.x = x;
this._handleRay(ray, triangle, voxelMesh);
rayOrigin.x = x;
const intersection = rayIntersectTriangleFastY(rayOrigin, triangle);
if (intersection) {
this._handleRayHit(intersection, triangle, voxelMesh);
}
}
}

ray.origin.z = bounds.min.z - 1;
ray.axis = Axes.z;
rayOrigin.z = bounds.min.z - 1;
for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
ray.origin.x = x;
rayOrigin.x = x;
for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
ray.origin.y = y;
this._handleRay(ray, triangle, voxelMesh);
rayOrigin.y = y;
const intersection = rayIntersectTriangleFastZ(rayOrigin, triangle);
if (intersection) {
this._handleRayHit(intersection, triangle, voxelMesh);
}
}
}
}

private _handleRay(ray: Ray, triangle: OtS_Triangle, voxelMesh: OtS_VoxelMesh) {
const intersection = rayIntersectTriangle(ray, triangle.data.v0.position, triangle.data.v1.position, triangle.data.v2.position);

if (intersection) {
const voxelPosition = new Vector3(
intersection.x,
intersection.y,
intersection.z,
).round();

let voxelColour: RGBA;
if (this._config.multisampling) {
const samples: RGBA[] = [];
for (let i = 0; i < 8; ++i) {
samples.push(this._getVoxelColour(
triangle,
Vector3.random().divScalar(2.0).add(voxelPosition),
))
}
voxelColour = RGBAUtil.average(...samples);
} else {
voxelColour = this._getVoxelColour(
private _handleRayHit(intersection: Vector3, triangle: OtS_Triangle, voxelMesh: OtS_VoxelMesh) {
const voxelPosition = new Vector3(
intersection.x,
intersection.y,
intersection.z,
).round();

let voxelColour: RGBA;
if (this._config.multisampling !== undefined) {
const samples: RGBA[] = [];
for (let i = 0; i < this._config.multisampling; ++i) {
samples.push(this._getVoxelColour(
triangle,
voxelPosition,
);
Vector3.random().divScalar(2.0).add(voxelPosition),
))
}

voxelMesh.addVoxel(voxelPosition.x, voxelPosition.y, voxelPosition.z, voxelColour, this._config.replaceMode);
voxelColour = RGBAUtil.average(...samples);
} else {
voxelColour = this._getVoxelColour(
triangle,
voxelPosition,
);
}

voxelMesh.addVoxel(voxelPosition.x, voxelPosition.y, voxelPosition.z, voxelColour, this._config.replaceMode);
}

private _getVoxelColour(triangle: OtS_Triangle, location: Vector3): RGBA {
Expand Down
93 changes: 85 additions & 8 deletions Core/src/ray.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { OtS_Triangle } from './ots_mesh';
import { ASSERT } from './util/error_util';
import { Vector3 } from './vector';

Expand Down Expand Up @@ -27,28 +28,65 @@ export interface Ray {
axis: Axes
}

export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) {
const edge1 = Vector3.sub(v1, v0);
const edge2 = Vector3.sub(v2, v0);
export type RayIntersect = (origin: Vector3, v0: Vector3, v1: Vector3, v2: Vector3) => (Vector3 | undefined);

const rayDirection = axesToDirection(ray.axis);
const h = Vector3.cross(rayDirection, edge2);
export function rayIntersectTriangleFastX(origin: Vector3, triangle: OtS_Triangle): (Vector3 | undefined) {
const edge1 = Vector3.sub(triangle.data.v1.position, triangle.data.v0.position);
const edge2 = Vector3.sub(triangle.data.v2.position, triangle.data.v0.position);

const h = new Vector3(0, -edge2.z, edge2.y); // Vector3.cross(rayDirection, edge2);
const a = Vector3.dot(edge1, h);

if (a > -EPSILON && a < EPSILON) {
return; // Ray is parallel to triangle
}

const f = 1.0 / a;
const s = Vector3.sub(origin, triangle.data.v0.position);
const u = f * Vector3.dot(s, h);

if (u < 0.0 || u > 1.0) {
return;
}

const q = Vector3.cross(s, edge1);
const v = f * q.x; // f * Vector3.dot(rayDirection, q);

if (v < 0.0 || u + v > 1.0) {
return;
}

const t = f * Vector3.dot(edge2, q);

if (t > EPSILON) {
const result = Vector3.copy(origin);
result.x += t;
return result;
//return Vector3.add(origin, Vector3.mulScalar(rayDirection, t));
}
}

export function rayIntersectTriangleFastY(origin: Vector3, triangle: OtS_Triangle): (Vector3 | undefined) {
const edge1 = Vector3.sub(triangle.data.v1.position, triangle.data.v0.position);
const edge2 = Vector3.sub(triangle.data.v2.position, triangle.data.v0.position);

const h = new Vector3(edge2.z, 0, -edge2.x); // Vector3.cross(rayDirection, edge2);
const a = Vector3.dot(edge1, h);

if (a > -EPSILON && a < EPSILON) {
return; // Ray is parallel to triangle
}

const f = 1.0 / a;
const s = Vector3.sub(ray.origin, v0);
const s = Vector3.sub(origin, triangle.data.v0.position);
const u = f * Vector3.dot(s, h);

if (u < 0.0 || u > 1.0) {
return;
}

const q = Vector3.cross(s, edge1);
const v = f * Vector3.dot(rayDirection, q);
const v = f * q.y; // f * Vector3.dot(rayDirection, q);

if (v < 0.0 || u + v > 1.0) {
return;
Expand All @@ -57,6 +95,45 @@ export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vec
const t = f * Vector3.dot(edge2, q);

if (t > EPSILON) {
return Vector3.add(ray.origin, Vector3.mulScalar(rayDirection, t));
const result = Vector3.copy(origin);
result.y += t;
return result;
//return Vector3.add(origin, Vector3.mulScalar(rayDirection, t));
}
}

export function rayIntersectTriangleFastZ(origin: Vector3, triangle: OtS_Triangle): (Vector3 | undefined) {
const edge1 = Vector3.sub(triangle.data.v1.position, triangle.data.v0.position);
const edge2 = Vector3.sub(triangle.data.v2.position, triangle.data.v0.position);

const h = new Vector3(-edge2.y, edge2.x, 0); // Vector3.cross(rayDirection, edge2);
const a = Vector3.dot(edge1, h);

if (a > -EPSILON && a < EPSILON) {
return; // Ray is parallel to triangle
}

const f = 1.0 / a;
const s = Vector3.sub(origin, triangle.data.v0.position);
const u = f * Vector3.dot(s, h);

if (u < 0.0 || u > 1.0) {
return;
}

const q = Vector3.cross(s, edge1);
const v = f * q.z; // f * Vector3.dot(rayDirection, q);

if (v < 0.0 || u + v > 1.0) {
return;
}

const t = f * Vector3.dot(edge2, q);

if (t > EPSILON) {
const result = Vector3.copy(origin);
result.z += t;
return result;
//return Vector3.add(origin, Vector3.mulScalar(rayDirection, t));
}
}
1 change: 0 additions & 1 deletion Sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ import { OtS_Colours } from 'ots-core/src/colour';
voxelMeshConverter.setConfig({
constraintAxis: 'y',
size: 380,
multisampling: false,
replaceMode: 'keep',
});

Expand Down

0 comments on commit 6e81858

Please sign in to comment.