forked from mirror/ObjToSchematic
Added texture-based coloured voxels, fixed UVs
This commit is contained in:
parent
9cd2c496c4
commit
f7d1487838
@ -5,6 +5,7 @@ uniform sampler2D u_texture;
|
||||
varying float v_lighting;
|
||||
varying vec4 v_occlusion;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec3 v_colour;
|
||||
|
||||
|
||||
void main() {
|
||||
@ -18,7 +19,8 @@ void main() {
|
||||
|
||||
float g = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c);
|
||||
|
||||
vec3 diffuse = texture2D(u_texture, v_texcoord).rgb;
|
||||
//vec3 diffuse = texture2D(u_texture, v_texcoord).rgb;
|
||||
vec3 diffuse = v_colour;
|
||||
gl_FragColor = vec4(diffuse * (v_lighting * g), 1.0);
|
||||
//gl_FragColor = vec4(vec3(v_lighting * g), 1.0);
|
||||
//gl_FragColor = vec4(v_colour.xyz * g, 1.0);
|
||||
|
@ -6,10 +6,12 @@ attribute vec4 position;
|
||||
attribute vec3 normal;
|
||||
attribute vec4 occlusion;
|
||||
attribute vec2 texcoord;
|
||||
attribute vec3 colour;
|
||||
|
||||
varying float v_lighting;
|
||||
varying vec4 v_occlusion;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec3 v_colour;
|
||||
|
||||
vec3 light = vec3(0.78, 0.98, 0.59);
|
||||
|
||||
@ -17,6 +19,7 @@ vec3 light = vec3(0.78, 0.98, 0.59);
|
||||
void main() {
|
||||
v_texcoord = texcoord;
|
||||
v_occlusion = occlusion;
|
||||
v_colour = colour;
|
||||
//float lighting = dot(light, abs(normal)) * (1.0 - occlusion * 0.2);
|
||||
//float lighting = 0.2 * occlusion;
|
||||
//v_colour = vec4(abs(normal), 1.0);
|
||||
|
@ -15,7 +15,9 @@ const canvas = document.querySelector("#c");
|
||||
let loadedMesh = null;
|
||||
|
||||
const mesh = new Mesh(renderer._gl, "./resources/mix.obj");
|
||||
renderer.registerMesh(mesh);
|
||||
//renderer.registerMesh(mesh);
|
||||
voxelManager.voxeliseMesh(mesh);
|
||||
renderer.registerVoxelMesh(voxelManager);
|
||||
//console.log(renderer._materialBuffers);
|
||||
|
||||
function showToastWithText(text, style) {
|
||||
|
@ -43,7 +43,7 @@ class Renderer {
|
||||
this._registerData(data);
|
||||
}
|
||||
|
||||
_registerVoxel(centre, voxelManager) {
|
||||
_registerVoxel(centre, voxelManager, colour) {
|
||||
let occlusions = new Array(6);
|
||||
// For each face
|
||||
for (let f = 0; f < 6; ++f) {
|
||||
@ -67,11 +67,15 @@ class Renderer {
|
||||
// Each vertex of a face needs the occlusion data for the other 3 vertices
|
||||
// in it's face, not just itself. Also flatten occlusion data.
|
||||
data.occlusion = new Array(96);
|
||||
data.colour = [];
|
||||
for (let j = 0; j < 6; ++j) {
|
||||
for (let k = 0; k < 16; ++k) {
|
||||
data.occlusion[j * 16 + k] = occlusions[j][k % 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
const l = data.position.length / 3;
|
||||
for (let i = 0; i < l; ++i)
|
||||
data.colour.push(colour[0], colour[1], colour[2]);
|
||||
|
||||
this._registerVoxels.add(data);
|
||||
}
|
||||
@ -91,7 +95,7 @@ class Renderer {
|
||||
mesh.materialTriangles[material].forEach((triangle) => {
|
||||
const data = GeometryTemplates.getTriangleBufferData(triangle, false);
|
||||
|
||||
console.log(data);
|
||||
//console.log(data);
|
||||
materialBuffer.add(data);
|
||||
});
|
||||
this._materialBuffers.push({
|
||||
@ -114,9 +118,16 @@ class Renderer {
|
||||
} else {
|
||||
this._setupOcclusions(voxelSize); // Setup arrays for calculating voxel ambient occlusion
|
||||
|
||||
for (let i = 0; i < voxelManager.voxels.length; ++i) {
|
||||
const voxel = voxelManager.voxels[i];
|
||||
const colour = voxelManager.voxelColours[i];
|
||||
this._registerVoxel(voxel, voxelManager, colour);
|
||||
}
|
||||
/*
|
||||
voxelManager.voxels.forEach((voxel) => {
|
||||
this._registerVoxel(voxel, voxelManager);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@ -297,7 +308,8 @@ class Renderer {
|
||||
{name: 'position', numComponents: 3},
|
||||
{name: 'normal', numComponents: 3},
|
||||
{name: 'occlusion', numComponents: 4},
|
||||
{name: 'texcoord', numComponents: 2}
|
||||
{name: 'texcoord', numComponents: 2},
|
||||
{name: 'colour', numComponents: 3},
|
||||
]);
|
||||
this._registerDefault = new SegmentedBuffer(bufferSize, [
|
||||
{name: 'position', numComponents: 3},
|
||||
|
27
src/texture.js
Normal file
27
src/texture.js
Normal file
@ -0,0 +1,27 @@
|
||||
const fs = require("fs");
|
||||
const png = require("pngjs").PNG;
|
||||
|
||||
class Texture {
|
||||
|
||||
constructor(filename) {
|
||||
const file = fs.readFileSync(filename);
|
||||
this._image = png.sync.read(file);
|
||||
}
|
||||
|
||||
getRGBA(u, v) {
|
||||
//u = 1 - u;
|
||||
v = 1 - v;
|
||||
|
||||
let x = Math.floor(this._image.width * u);
|
||||
let y = Math.floor(this._image.height * v);
|
||||
|
||||
x = Math.max(0, Math.min(x, this._image.width - 1));
|
||||
y = Math.max(0, Math.min(y, this._image.height - 1));
|
||||
|
||||
const index = this._image.bpp * (this._image.width * y + x);
|
||||
return this._image.data.slice(index, index + this._image.bpp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.Texture = Texture;
|
@ -109,12 +109,12 @@ class Vector3 {
|
||||
return this.x == vec.x && this.y == vec.y && this.z == vec.z;
|
||||
}
|
||||
|
||||
_magnitude() {
|
||||
magnitude() {
|
||||
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));
|
||||
}
|
||||
|
||||
normalise() {
|
||||
const mag = this._magnitude();
|
||||
const mag = this.magnitude();
|
||||
this.x /= mag;
|
||||
this.y /= mag;
|
||||
this.z /= mag;
|
||||
|
@ -1,12 +1,14 @@
|
||||
const { AABB, CubeAABB } = require("./aabb.js");
|
||||
const { Vector3 } = require("./vector.js");
|
||||
const { HashSet, HashMap } = require('./hash_map.js');
|
||||
const { Texture } = require("./texture.js");
|
||||
|
||||
class VoxelManager {
|
||||
|
||||
constructor(voxelSize) {
|
||||
this._voxelSize = voxelSize;
|
||||
this.voxels = [];
|
||||
this.voxelColours = [];
|
||||
this.triangleAABBs = [];
|
||||
this.failedAABBs = [];
|
||||
|
||||
@ -25,6 +27,7 @@ class VoxelManager {
|
||||
|
||||
_clearVoxels() {
|
||||
this.voxels = [];
|
||||
this.voxelColours = [];
|
||||
this.failedAABBs = [];
|
||||
|
||||
this.minX = Infinity; // JavaScript crack
|
||||
@ -81,7 +84,7 @@ class VoxelManager {
|
||||
return this.voxelsHash.contains(pos);
|
||||
}
|
||||
|
||||
addVoxel(vec) {
|
||||
addVoxel(vec, colour) {
|
||||
|
||||
// (0.5, 0.5, 0.5) -> (0, 0, 0);
|
||||
vec = Vector3.subScalar(vec, this._voxelSize / 2);
|
||||
@ -100,6 +103,7 @@ class VoxelManager {
|
||||
return;
|
||||
}
|
||||
this.voxels.push(pos);
|
||||
this.voxelColours.push(colour);
|
||||
this.voxelsHash.add(pos);
|
||||
|
||||
this.minX = Math.min(this.minX, vec.x);
|
||||
@ -243,6 +247,67 @@ class VoxelManager {
|
||||
this.triangleAABBs = newTriangleAABBs;
|
||||
}
|
||||
|
||||
_getVoxelColour(triangle, centre) {
|
||||
const a = triangle.v0;
|
||||
const b = triangle.v1;
|
||||
const c = triangle.v2;
|
||||
const p = centre;
|
||||
|
||||
const uv0 = triangle.uv0;
|
||||
const uv1 = triangle.uv1;
|
||||
const uv2 = triangle.uv2;
|
||||
|
||||
const delta = 0.5 * Vector3.sub(a, b).magnitude() * Vector3.sub(a, c).magnitude();
|
||||
const da = 0.5 * Vector3.sub(p, b).magnitude() * Vector3.sub(p, c).magnitude();
|
||||
const db = 0.5 * Vector3.sub(p, a).magnitude() * Vector3.sub(p, c).magnitude();
|
||||
const dc = 0.5 * Vector3.sub(p, a).magnitude() * Vector3.sub(p, b).magnitude();
|
||||
|
||||
const ka = da / delta;
|
||||
const kb = db / delta;
|
||||
const kc = dc / delta;
|
||||
|
||||
const u = uv0[0] * ka + uv1[0] * kb + uv2[0] * kc;
|
||||
const v = uv0[1] * ka + uv1[1] * kb + uv2[1] * kc;
|
||||
|
||||
//const rgba = triangle.material.texture.getRGBA(u, v);
|
||||
const rgba = this._currentTexture.getRGBA(u, v);
|
||||
if (rgba.length == 0) {
|
||||
return [1.0, 0.0, 0.0];
|
||||
}
|
||||
//return [0.0, 0.0, 0.0];
|
||||
return [rgba[0]/255, rgba[1]/255, rgba[2]/255];
|
||||
}
|
||||
|
||||
_getVoxelColour2(triangle, centre) {
|
||||
const p1 = triangle.v0;
|
||||
const p2 = triangle.v1;
|
||||
const p3 = triangle.v2;
|
||||
|
||||
const uv1 = triangle.uv0;
|
||||
const uv2 = triangle.uv1;
|
||||
const uv3 = triangle.uv2;
|
||||
|
||||
const f1 = Vector3.sub(p1, centre);
|
||||
const f2 = Vector3.sub(p2, centre);
|
||||
const f3 = Vector3.sub(p3, centre);
|
||||
|
||||
const a = Vector3.cross(Vector3.sub(p1, p2), Vector3.sub(p1, p3)).magnitude();
|
||||
const a1 = Vector3.cross(f2, f3).magnitude() / a;
|
||||
const a2 = Vector3.cross(f3, f1).magnitude() / a;
|
||||
const a3 = Vector3.cross(f1, f2).magnitude() / a;
|
||||
|
||||
const u = uv1[0] * a1 + uv2[0] * a2 + uv3[0] * a3;
|
||||
const v = uv1[1] * a1 + uv2[1] * a2 + uv3[1] * a3;
|
||||
|
||||
//const rgba = triangle.material.texture.getRGBA(u, v);
|
||||
const rgba = this._currentTexture.getRGBA(u, v);
|
||||
if (rgba.length == 0) {
|
||||
return [1.0, 0.0, 0.0];
|
||||
}
|
||||
//return [0.0, 0.0, 0.0];
|
||||
return [rgba[0]/255, rgba[1]/255, rgba[2]/255];
|
||||
}
|
||||
|
||||
voxeliseTriangle(triangle) {
|
||||
const cubeAABB = this._getTriangleCubeAABB(triangle);
|
||||
|
||||
@ -257,7 +322,7 @@ class VoxelManager {
|
||||
queue.push(...aabb.subdivide());
|
||||
} else {
|
||||
// We've reached the voxel level, stop
|
||||
this.addVoxel(aabb.centre);
|
||||
this.addVoxel(aabb.centre, this._getVoxelColour2(triangle, aabb.centre));
|
||||
triangleAABBs.push(aabb);
|
||||
}
|
||||
} else {
|
||||
@ -269,8 +334,12 @@ class VoxelManager {
|
||||
}
|
||||
|
||||
voxeliseMesh(mesh) {
|
||||
for (const triangle of mesh.triangles) {
|
||||
this.voxeliseTriangle(triangle);
|
||||
for (const material in mesh.materialTriangles) {
|
||||
this._currentTexture = new Texture(mesh._materials[material].diffuseTexturePath);
|
||||
console.log(this._currentTexture);
|
||||
for (const triangle of mesh.materialTriangles[material]) {
|
||||
this.voxeliseTriangle(triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user