forked from mirror/ObjToSchematic
Added x-based greedy voxel meshing
This commit is contained in:
parent
69affc8a8b
commit
d304993362
10
index.html
10
index.html
@ -17,12 +17,18 @@
|
||||
<button id="objBtn" class="btn btn-primary" type="button" id="inputGroupFileAddon04">Load</button>
|
||||
</div>
|
||||
<div class="input-group w-25 mx-auto">
|
||||
<label class="input-group-text" for="inputGroupFileAddon03">Options</label>
|
||||
<input type="number" min="0.1" step="0.1" value="1.0" class="form-control" id="voxelInput" aria-describedby="inputGroupFileAddon03" aria-label="Voxel size" disabled>
|
||||
<label class="input-group-text" for="inputGroupFileAddon03">Voxel size</label>
|
||||
<input type="number" min="0.1" step="0.1" value="0.1" class="form-control" id="voxelInput" aria-describedby="inputGroupFileAddon03" aria-label="Voxel size" disabled>
|
||||
<button id="voxelBtn" class="btn btn-primary" type="button" id="inputGroupFileAddon03" disabled>Voxelise</button>
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
<div class="progress" style="height: 1px;">
|
||||
<div class="progress-bar" role="progressbar" style="width: 25%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
|
||||
<canvas id="c"></canvas>
|
||||
</body>
|
||||
|
||||
|
@ -3,7 +3,8 @@ const { Mesh } = require('./src/mesh.js');
|
||||
const { VoxelManager } = require('./src/voxel_manager.js');
|
||||
const { Vector3 } = require('./src/vector.js');
|
||||
|
||||
const voxelSize = 0.5;
|
||||
//const voxelSize = document.querySelector("#voxelInput").value;
|
||||
const voxelSize = 0.05;
|
||||
let renderer = new Renderer(voxelSize);
|
||||
const voxelManager = new VoxelManager(voxelSize);
|
||||
|
||||
@ -63,6 +64,29 @@ document.querySelector("#voxelBtn").addEventListener('click', () => {
|
||||
renderer.compileRegister();
|
||||
});
|
||||
|
||||
loadedMesh = new Mesh("./resources/suzanne.obj");
|
||||
voxelManager.voxeliseMesh(loadedMesh);
|
||||
|
||||
const useNew = true;
|
||||
const useDebug = true;
|
||||
|
||||
if (useNew) {
|
||||
const mesh = voxelManager.buildMesh();
|
||||
for (const box of mesh) {
|
||||
renderer.registerBox(box.centre, box.size, useDebug);
|
||||
}
|
||||
} else {
|
||||
renderer.registerVoxels(voxelManager.voxels, useDebug);
|
||||
}
|
||||
|
||||
//console.log(voxelManager.voxels.length, "->", k.length, voxelManager.voxels.length/k.length);
|
||||
|
||||
|
||||
|
||||
//renderer.setStroke(new Vector3(1.0, 0.0, 0.0));
|
||||
//renderer.registerVoxels(voxelManager.voxels, true);
|
||||
renderer.compileRegister();
|
||||
|
||||
|
||||
function render(time) {
|
||||
resizeCanvas();
|
||||
|
@ -14,7 +14,6 @@ class HashMap {
|
||||
|
||||
add(key, value) {
|
||||
const binIndex = this._getBin(key);
|
||||
console.log(binIndex);
|
||||
|
||||
if (!this.bins[binIndex]) {
|
||||
this.bins[binIndex] = [ {key: key, value: value} ];
|
||||
@ -39,6 +38,46 @@ class HashMap {
|
||||
}
|
||||
}
|
||||
|
||||
class HashSet {
|
||||
|
||||
constructor(numBins) {
|
||||
this.numBins = numBins;
|
||||
this.bins = new Array(numBins);
|
||||
}
|
||||
|
||||
_getBin(key) {
|
||||
const hash = key.hash(); // A bit naughty
|
||||
return Math.abs(hash) % this.numBins;
|
||||
}
|
||||
|
||||
add(key) {
|
||||
const binIndex = this._getBin(key);
|
||||
|
||||
if (!this.bins[binIndex]) {
|
||||
this.bins[binIndex] = [ key ];
|
||||
} else {
|
||||
this.bins[binIndex].push(key);
|
||||
}
|
||||
}
|
||||
|
||||
contains(key) {
|
||||
const binIndex = this._getBin(key);
|
||||
|
||||
if (!this.bins[binIndex]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const list = this.bins[binIndex];
|
||||
for (const item of list) {
|
||||
if (item.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const hashMap = new HashMap(4);
|
||||
const v = new Vector3(2.0, 2.0, 3.0);
|
||||
const v2 = new Vector3(2.0, 2.0, 5.0);
|
||||
@ -57,4 +96,8 @@ console.log(hashMap.bins[3]);
|
||||
console.log(hashMap.get(v));
|
||||
console.log(hashMap.get(v2));
|
||||
console.log(hashMap.get(v3));
|
||||
console.log(hashMap.get(v4));
|
||||
console.log(hashMap.get(v4));
|
||||
*/
|
||||
|
||||
module.exports.HashMap = HashMap;
|
||||
module.exports.HashSet = HashSet;
|
@ -32,7 +32,7 @@ class Renderer {
|
||||
|
||||
this._voxelSize = voxelSize;
|
||||
this._voxelSizeVector = new Vector3(voxelSize, voxelSize, voxelSize);
|
||||
this._cube = twgl.primitives.createCubeVertices(this._voxelSize);
|
||||
this._cube = twgl.primitives.createCubeVertices(1.0);
|
||||
|
||||
this._registersOpen = true;
|
||||
}
|
||||
@ -139,7 +139,6 @@ class Renderer {
|
||||
setVoxelSize(voxelSize) {
|
||||
this._voxelSize = voxelSize;
|
||||
this._voxelSizeVector = new Vector3(voxelSize, voxelSize, voxelSize);
|
||||
this._cube = twgl.primitives.createCubeVertices(this._voxelSize);
|
||||
}
|
||||
|
||||
_drawDebugRegisters() {
|
||||
@ -195,6 +194,7 @@ class Renderer {
|
||||
]
|
||||
};
|
||||
} else {
|
||||
|
||||
let cube = {
|
||||
position: new Float32Array(72),
|
||||
normal: new Float32Array(72),
|
||||
@ -206,9 +206,9 @@ class Renderer {
|
||||
cube.indices.set(this._cube.indices);
|
||||
|
||||
for (let i = 0; i < 72; i += 3) {
|
||||
cube.position[i + 0] += centre.x;
|
||||
cube.position[i + 1] += centre.y;
|
||||
cube.position[i + 2] += centre.z;
|
||||
cube.position[i + 0] = (cube.position[i + 0] * size.x) + centre.x;
|
||||
cube.position[i + 1] = (cube.position[i + 1] * size.y) + centre.y;
|
||||
cube.position[i + 2] = (cube.position[i + 2] * size.z) + centre.z;
|
||||
}
|
||||
|
||||
return cube;
|
||||
@ -272,6 +272,7 @@ class Renderer {
|
||||
// Use when drawing the same thing each frame
|
||||
registerBox(centre, size, debug) {
|
||||
const data = this._getBoxData(centre, size, debug);
|
||||
//console.log(data);
|
||||
this._addDataToRegister(data, debug);
|
||||
}
|
||||
|
||||
@ -299,9 +300,16 @@ class Renderer {
|
||||
}
|
||||
|
||||
registerVoxels(voxelCentres, debug) {
|
||||
/*
|
||||
for (let i = 0; i < voxelCentres.length; ++i) {
|
||||
console.log(i / voxelCentres.length);
|
||||
this.registerVoxel(voxelCentres[i], debug);
|
||||
}
|
||||
*/
|
||||
for (const voxelCentre of voxelCentres) {
|
||||
this.registerVoxel(voxelCentre, debug);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_cycleDebugRegister() {
|
||||
@ -317,6 +325,10 @@ class Renderer {
|
||||
//console.log("Cycling Registers");
|
||||
}
|
||||
|
||||
_willDataOverflowBuffer(data) {
|
||||
|
||||
}
|
||||
|
||||
_addDataToRegister(data, debug) {
|
||||
if (!this._registersOpen) {
|
||||
console.error("Trying to register object when register is closed. Register before calling compileRegister()");
|
||||
|
@ -26,6 +26,14 @@ class Vector3 {
|
||||
);
|
||||
}
|
||||
|
||||
static subScalar(vec, scalar) {
|
||||
return new Vector3(
|
||||
vec.x - scalar,
|
||||
vec.y - scalar,
|
||||
vec.z - scalar
|
||||
);
|
||||
}
|
||||
|
||||
static dot(vecA, vecB) {
|
||||
return vecA.x * vecB.x + vecA.y * vecB.y + vecA.z * vecB.z;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
const { AABB, CubeAABB } = require("./aabb.js");
|
||||
const { Vector3 } = require("./vector.js");
|
||||
const { HashSet } = require('./hash_map.js');
|
||||
|
||||
class VoxelManager {
|
||||
|
||||
@ -7,6 +8,14 @@ class VoxelManager {
|
||||
this._voxelSize = voxelSize;
|
||||
this.voxels = [];
|
||||
this.failedAABBs = [];
|
||||
|
||||
this.minX = Infinity; // JavaScript crack
|
||||
this.minY = Infinity;
|
||||
this.minZ = Infinity;
|
||||
this.maxX = -Infinity;
|
||||
this.maxY = -Infinity;
|
||||
this.maxZ = -Infinity;
|
||||
this.voxelsHash = new HashSet(512);
|
||||
}
|
||||
|
||||
setVoxelSize(voxelSize) {
|
||||
@ -35,6 +44,66 @@ class VoxelManager {
|
||||
return cubeAABB;
|
||||
}
|
||||
|
||||
_voxelCentreToPosition(vec) {
|
||||
//Vector3.round(Vector3.subScalar(Vector3.divScalar(vec, this._voxelSize), 0.5));
|
||||
return new Vector3(
|
||||
Math.round((vec.x / this._voxelSize) - 0.5),
|
||||
Math.round((vec.y / this._voxelSize) - 0.5),
|
||||
Math.round((vec.z / this._voxelSize) - 0.5)
|
||||
);
|
||||
}
|
||||
|
||||
addVoxel(vec) {
|
||||
this.voxels.push(vec);
|
||||
|
||||
const pos = this._voxelCentreToPosition(vec);
|
||||
this.voxelsHash.add(pos, true);
|
||||
|
||||
this.minX = Math.min(this.minX, vec.x);
|
||||
this.minY = Math.min(this.minY, vec.y);
|
||||
this.minZ = Math.min(this.minZ, vec.z);
|
||||
this.maxX = Math.max(this.maxX, vec.x);
|
||||
this.maxY = Math.max(this.maxY, vec.y);
|
||||
this.maxZ = Math.max(this.maxZ, vec.z);
|
||||
}
|
||||
|
||||
buildMesh() {
|
||||
|
||||
let mesh = [];
|
||||
|
||||
//const minPos = this._voxelCentreToPosition(new Vector3(this.minX, this.minY, this.minZ));
|
||||
//const maxPos = this._voxelCentreToPosition(new Vector3(this.maxX, this.maxY, this.maxZ));
|
||||
|
||||
for (let y = this.minY; y <= this.maxY; y += this._voxelSize) {
|
||||
for (let z = this.minZ; z <= this.maxZ; z += this._voxelSize) {
|
||||
let penDown = false;
|
||||
let begin = null;
|
||||
|
||||
for (let x = this.minX; x < this.maxX + 2 * this._voxelSize; x += this._voxelSize) {
|
||||
const vec = new Vector3(x, y, z);
|
||||
const pos = this._voxelCentreToPosition(vec);
|
||||
const voxelHere = this.voxelsHash.contains(pos);
|
||||
|
||||
if (!penDown && voxelHere) {
|
||||
penDown = true;
|
||||
begin = vec;
|
||||
}
|
||||
else if (penDown && !voxelHere) {
|
||||
penDown = false;
|
||||
let end = new Vector3(x - this._voxelSize, y, z);
|
||||
|
||||
let centre = Vector3.divScalar(Vector3.add(begin, end), 2);
|
||||
let size = new Vector3(end.x - begin.x + this._voxelSize, this._voxelSize, this._voxelSize);
|
||||
|
||||
mesh.push({centre: centre, size: size});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
voxeliseTriangle(triangle) {
|
||||
const cubeAABB = this._getTriangleCubeAABB(triangle);
|
||||
|
||||
@ -51,7 +120,8 @@ class VoxelManager {
|
||||
} else {
|
||||
// We've reached the voxel level, stop
|
||||
//renderer.registerBox(aabb.centre, aabb.size);
|
||||
this.voxels.push(aabb.centre);
|
||||
//this.voxels.push(aabb.centre);
|
||||
this.addVoxel(aabb.centre);
|
||||
}
|
||||
} else {
|
||||
this.failedAABBs.push(aabb);
|
||||
|
Loading…
Reference in New Issue
Block a user