forked from mirror/ObjToSchematic
Added normal-corrected voxelisation, resolves #30
This commit is contained in:
parent
cee9871bfa
commit
4151083ce3
38
src/ray.ts
38
src/ray.ts
@ -27,30 +27,30 @@ export interface Ray {
|
||||
axis: Axes
|
||||
}
|
||||
|
||||
export function generateRays(v0: Vector3, v1: Vector3, v2: Vector3): Array<Ray> {
|
||||
export function generateRays(v0: Vector3, v1: Vector3, v2: Vector3, offset: 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)),
|
||||
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.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)),
|
||||
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);
|
||||
traverseY(rayList, bounds);
|
||||
traverseZ(rayList, bounds);
|
||||
traverseX(rayList, bounds, offset);
|
||||
traverseY(rayList, bounds, offset);
|
||||
traverseZ(rayList, bounds, offset);
|
||||
return rayList;
|
||||
}
|
||||
|
||||
function 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) {
|
||||
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,
|
||||
@ -59,9 +59,9 @@ function traverseX(rayList: Array<Ray>, bounds: Bounds) {
|
||||
}
|
||||
}
|
||||
|
||||
function 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) {
|
||||
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,
|
||||
@ -70,9 +70,9 @@ function traverseY(rayList: Array<Ray>, bounds: Bounds) {
|
||||
}
|
||||
}
|
||||
|
||||
function 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) {
|
||||
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,
|
||||
|
16
src/util.ts
16
src/util.ts
@ -82,10 +82,6 @@ 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 red(): RGB {
|
||||
return new RGB(1.0, 0.0, 0.0);
|
||||
}
|
||||
@ -98,6 +94,18 @@ export class RGB {
|
||||
return new RGB(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public static get yellow(): RGB {
|
||||
return new RGB(1.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
public static get cyan(): RGB {
|
||||
return new RGB(0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
public static get magenta(): RGB {
|
||||
return new RGB(1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public static get black(): RGB {
|
||||
return new RGB(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ export class RayVoxeliser extends IVoxeliser {
|
||||
private _voxelMesh?: VoxelMesh;
|
||||
private _voxelMeshParams?: VoxelMeshParams;
|
||||
private _scale!: number;
|
||||
private _size!: Vector3;
|
||||
private _offset!: Vector3;
|
||||
|
||||
public override voxelise(mesh: Mesh, voxelMeshParams: VoxelMeshParams): VoxelMesh {
|
||||
@ -24,40 +25,49 @@ export class RayVoxeliser extends IVoxeliser {
|
||||
this._voxelMesh = new VoxelMesh(mesh, voxelMeshParams);
|
||||
this._voxelMeshParams = voxelMeshParams;
|
||||
|
||||
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);
|
||||
this._scale = (voxelMeshParams.desiredHeight) / Mesh.desiredHeight;
|
||||
const useMesh = mesh.copy();
|
||||
|
||||
useMesh.scaleMesh(this._scale);
|
||||
useMesh.translateMesh(this._offset);
|
||||
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);
|
||||
this._voxeliseTri(uvTriangle, material, normals);
|
||||
}
|
||||
|
||||
return this._voxelMesh;
|
||||
}
|
||||
|
||||
private _voxeliseTri(triangle: UVTriangle, materialName: string) {
|
||||
const rayList = generateRays(triangle.v0, triangle.v1, triangle.v2);
|
||||
private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3}) {
|
||||
const rayList = generateRays(triangle.v0, triangle.v1, triangle.v2,
|
||||
this._offset,
|
||||
);
|
||||
|
||||
rayList.forEach((ray) => {
|
||||
const rayOriginWorld = Vector3.divScalar(ray.origin, this._scale).sub(this._offset);
|
||||
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.cross(
|
||||
rayOriginWorld,
|
||||
0.1,
|
||||
ray.axis === Axes.x ? RGB.red : (ray.axis === Axes.y ? RGB.green : RGB.blue),
|
||||
));
|
||||
|
||||
const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
|
||||
if (intersection) {
|
||||
this._voxelMesh!.debugBuffer.add(DebugGeometryTemplates.arrow(
|
||||
rayOriginWorld,
|
||||
Vector3.divScalar(intersection, this._scale).sub(this._offset),
|
||||
ray.axis === Axes.x ? RGB.red : (ray.axis === Axes.y ? RGB.green : RGB.blue),
|
||||
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:
|
||||
@ -70,6 +80,13 @@ export class RayVoxeliser extends IVoxeliser {
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user