forked from mirror/ObjToSchematic
Rewrite of OBJ parsing
This commit is contained in:
parent
abd71d114d
commit
7056e62aa9
@ -69,6 +69,8 @@ export class AppContext {
|
||||
|
||||
try {
|
||||
this._loadedMesh = new Mesh(files[0].path, this._gl);
|
||||
this._loadedMesh.loadTextures(this._gl);
|
||||
|
||||
} catch (err: any) {
|
||||
this._showToast(err.message, ToastColour.RED);
|
||||
console.log(err);
|
||||
@ -129,6 +131,7 @@ export class AppContext {
|
||||
this._renderer.compile();
|
||||
} catch (err: any) {
|
||||
this._showToast(err.message, ToastColour.RED);
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,8 @@
|
||||
import * as twgl from "twgl.js";
|
||||
import { Triangle } from "./triangle";
|
||||
import { Vector3 } from "./vector";
|
||||
import { UV } from "./util";
|
||||
import { VoxelData } from "./buffer";
|
||||
|
||||
enum DataType {
|
||||
PositionIndexData,
|
||||
PositionTexcoordNormalIndexData
|
||||
}
|
||||
|
||||
/*
|
||||
export interface PositionIndexData {
|
||||
type: DataType.PositionIndexData,
|
||||
position: Float32Array,
|
||||
indices: Uint16Array
|
||||
}
|
||||
|
||||
export interface PositionTexcoordNormalIndexData extends PositionIndexData {
|
||||
type: DataType.PositionTexcoordNormalIndexData,
|
||||
|
||||
texcoord: Float32Array,
|
||||
normal: Float32Array
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
export class GeometryTemplates {
|
||||
|
||||
@ -34,13 +13,14 @@ export class GeometryTemplates {
|
||||
const b = triangle.v1;
|
||||
const c = triangle.v2;
|
||||
const n = triangle.normal;
|
||||
//console.log(triangle);
|
||||
|
||||
if (debug) {
|
||||
return {
|
||||
position: new Float32Array([
|
||||
a.x, a.y, a.z,
|
||||
b.x, b.y, b.z,
|
||||
c.x, c.y, c.z,
|
||||
a.position.x, a.position.y, a.position.z,
|
||||
b.position.x, b.position.y, b.position.z,
|
||||
c.position.x, c.position.y, c.position.z,
|
||||
]),
|
||||
indices: new Uint16Array([
|
||||
0, 1,
|
||||
@ -51,14 +31,14 @@ export class GeometryTemplates {
|
||||
} else {
|
||||
return {
|
||||
position: new Float32Array([
|
||||
a.x, a.y, a.z,
|
||||
b.x, b.y, b.z,
|
||||
c.x, c.y, c.z,
|
||||
a.position.x, a.position.y, a.position.z,
|
||||
b.position.x, b.position.y, b.position.z,
|
||||
c.position.x, c.position.y, c.position.z,
|
||||
]),
|
||||
texcoord: new Float32Array([
|
||||
triangle.uv0.u, triangle.uv0.v,
|
||||
triangle.uv1.u, triangle.uv1.v,
|
||||
triangle.uv2.u, triangle.uv2.v
|
||||
a.texcoord.u, a.texcoord.v,
|
||||
b.texcoord.u, b.texcoord.v,
|
||||
c.texcoord.u, c.texcoord.v
|
||||
]),
|
||||
normal: new Float32Array([
|
||||
n.x, n.y, n.z,
|
||||
|
385
src/mesh.ts
385
src/mesh.ts
@ -1,36 +1,65 @@
|
||||
import * as twgl from "twgl.js";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
//import { expandVertexData } from "expand-vertex-data";
|
||||
const expandVertexData: any = require("expand-vertex-data");
|
||||
|
||||
import { Triangle } from "./triangle";
|
||||
import { Vector3 } from "./vector";
|
||||
import { RGB } from "./util";
|
||||
import { Texture } from "./texture";
|
||||
import { RGB, UV } from "./util";
|
||||
import { TextureFormat } from "./texture";
|
||||
|
||||
type VertexMap<T> = { [index: number]: T };
|
||||
|
||||
|
||||
export class Vertex {
|
||||
|
||||
public position: Vector3;
|
||||
public texcoord: UV
|
||||
public normal: Vector3;
|
||||
|
||||
constructor(position: Vector3, texcoord: UV, normal: Vector3) {
|
||||
this.position = position;
|
||||
this.texcoord = texcoord;
|
||||
if (!texcoord) {
|
||||
this.texcoord = { u: 0, v: 0 };
|
||||
}
|
||||
|
||||
this.normal = normal;
|
||||
}
|
||||
|
||||
public static parseFromOBJ(
|
||||
vertexToken: string,
|
||||
vertexPositionMap: VertexMap<Vector3>,
|
||||
vertexTexcoordMap: VertexMap<UV>,
|
||||
vertexNormalMap: VertexMap<Vector3>,
|
||||
) {
|
||||
const tokens = vertexToken.split("/");
|
||||
|
||||
const positionIndex = parseFloat(tokens[0]);
|
||||
const texcoordIndex = parseFloat(tokens[1]);
|
||||
const normalIndex = parseFloat(tokens[2]);
|
||||
|
||||
const position = vertexPositionMap[positionIndex];
|
||||
const texcoord = vertexTexcoordMap[texcoordIndex];
|
||||
const normal = vertexNormalMap[normalIndex];
|
||||
|
||||
return new Vertex(position, texcoord, normal);
|
||||
}
|
||||
|
||||
export enum TextureFormat {
|
||||
PNG,
|
||||
JPEG
|
||||
}
|
||||
|
||||
interface objData {
|
||||
vertexNormals: Array<number>;
|
||||
vertexUVs: Array<number>;
|
||||
vertexPositions: Array<number>;
|
||||
vertexNormalIndices: Array<number>;
|
||||
vertexUVIndices: Array<number>;
|
||||
vertexPositionIndices: Array<number>;
|
||||
vertexMaterial: Array<string>;
|
||||
};
|
||||
|
||||
interface Materials {
|
||||
[materialName: string]: (FillMaterial | TextureMaterial)
|
||||
}
|
||||
|
||||
interface ParsedOBJ {
|
||||
mtlPath: (string | undefined),
|
||||
materials: Array<Material>
|
||||
}
|
||||
|
||||
export interface FillMaterial {
|
||||
readonly type: MaterialType.Fill
|
||||
diffuseColour: RGB
|
||||
readonly type: MaterialType.Fill,
|
||||
diffuseColour: RGB
|
||||
}
|
||||
|
||||
export interface TextureMaterial {
|
||||
@ -50,72 +79,61 @@ export interface MaterialTriangles {
|
||||
triangles: Array<Triangle>
|
||||
}
|
||||
|
||||
class Material {
|
||||
|
||||
public name: string;
|
||||
public faces: Array<Triangle>;
|
||||
public materialData: (FillMaterial | TextureMaterial);
|
||||
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
this.faces = [];
|
||||
|
||||
let material: FillMaterial = { diffuseColour: { r: 1, g: 1, b: 1 }, type: MaterialType.Fill}
|
||||
this.materialData = material;
|
||||
}
|
||||
|
||||
public addFace(face: Triangle) {
|
||||
this.faces.push(face);
|
||||
}
|
||||
|
||||
public isFilled(): boolean {
|
||||
return this.name !== "" && this.faces.length > 0;
|
||||
}
|
||||
|
||||
public attachMTLData(materialData: (FillMaterial | TextureMaterial)) {
|
||||
this.materialData = materialData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class Mesh {
|
||||
|
||||
//public materialTriangles: {[materialName: string]: Array<MaterialTriangles>};
|
||||
public materialTriangles: Array<MaterialTriangles> = [];
|
||||
|
||||
private _gl: WebGLRenderingContext;
|
||||
private objPath: path.ParsedPath;
|
||||
private mtlPath?: string;
|
||||
//private _materials: Materials;
|
||||
private _data: {
|
||||
position: Float32Array;
|
||||
texcoord: Float32Array;
|
||||
indices: Uint16Array;
|
||||
materialNames: Array<string>;
|
||||
}
|
||||
private _materialIndices: {[materialName: string]: Array<number>}
|
||||
public materials: Array<Material>
|
||||
|
||||
constructor(objPathString: string, gl: WebGLRenderingContext) {
|
||||
|
||||
this.objPath = path.parse(objPathString);
|
||||
//this.materialTriangles: Array<MaterialTriangles>;
|
||||
this._gl = gl;
|
||||
|
||||
// Parse .obj
|
||||
const wavefrontString = fs.readFileSync(objPathString).toString('utf8');
|
||||
const parsedJSON = this._parseWavefrontObj(wavefrontString);
|
||||
|
||||
if (this.mtlPath) {
|
||||
if (!path.isAbsolute(this.mtlPath)) {
|
||||
this.mtlPath = path.join(this.objPath.dir, this.mtlPath);
|
||||
}
|
||||
} else {
|
||||
const parsedOBJ = this._parseOBJFile(wavefrontString);
|
||||
|
||||
// TODO: Create blank .mtl when not found
|
||||
if (!parsedOBJ.mtlPath) {
|
||||
throw Error("No .mtl file found.");
|
||||
}
|
||||
|
||||
// Parse .mtl
|
||||
const materialString = fs.readFileSync(this.mtlPath).toString('utf8');
|
||||
const materials = this._parseMaterial(materialString);
|
||||
|
||||
// FIXME: Fix quad faces
|
||||
//console.log(expandVertexData.expandVertexData(null, null));
|
||||
const expanded = expandVertexData(parsedJSON, {facesToTriangles: true});
|
||||
|
||||
this._data = {
|
||||
position: expanded.positions,
|
||||
texcoord: expanded.uvs,
|
||||
indices: expanded.positionIndices,
|
||||
materialNames: parsedJSON.vertexMaterial
|
||||
};
|
||||
|
||||
this._materialIndices = {};
|
||||
for (let i = 0; i < parsedJSON.vertexMaterial.length; ++i) {
|
||||
const materialName = parsedJSON.vertexMaterial[i];
|
||||
const index = expanded.positionIndices[i];
|
||||
if (this._materialIndices[materialName]) {
|
||||
this._materialIndices[materialName].push(index);
|
||||
} else {
|
||||
this._materialIndices[materialName] = [index];
|
||||
}
|
||||
|
||||
const objPath = path.parse(objPathString);
|
||||
if (!path.isAbsolute(parsedOBJ.mtlPath)) {
|
||||
parsedOBJ.mtlPath = path.join(objPath.dir, parsedOBJ.mtlPath);
|
||||
}
|
||||
|
||||
// Parse .mtl
|
||||
const materialString = fs.readFileSync(parsedOBJ.mtlPath).toString('utf8');
|
||||
const parsedMTL = this._parseMaterial(materialString, objPath);
|
||||
|
||||
this._parseTriangles(materials);
|
||||
|
||||
this.materials = this._mergeMaterialData(parsedOBJ, parsedMTL);
|
||||
this._centreMesh();
|
||||
this._normaliseMesh();
|
||||
|
||||
this._loadTextures(materials);
|
||||
}
|
||||
|
||||
private _addMaterial(materialsJSON: Materials, materialName: string, materialDiffuseColour: RGB, materialDiffuseTexturePath: string, materialFormat: TextureFormat) {
|
||||
@ -135,13 +153,13 @@ export class Mesh {
|
||||
}
|
||||
|
||||
// TODO: Rewrite
|
||||
private _parseMaterial(materialString: string): Materials {
|
||||
private _parseMaterial(materialString: string, objPath: path.ParsedPath): Materials {
|
||||
var materialsJSON: Materials = {};
|
||||
|
||||
const lines = materialString.split('\n');
|
||||
|
||||
let materialName: string = "";
|
||||
let materialDiffuseColour: RGB = {r: 1.0, g: 1.0, b: 1.0};
|
||||
let materialDiffuseColour: RGB = { r: 1.0, g: 1.0, b: 1.0 };
|
||||
let materialDiffuseTexturePath: string = "";
|
||||
let materialTextureFormat: TextureFormat = TextureFormat.PNG;
|
||||
|
||||
@ -153,17 +171,17 @@ export class Mesh {
|
||||
case "newmtl":
|
||||
this._addMaterial(materialsJSON, materialName, materialDiffuseColour, materialDiffuseTexturePath, materialTextureFormat);
|
||||
materialName = lineTokens[1];
|
||||
materialDiffuseColour = {r: 0, g: 0, b: 0};
|
||||
materialDiffuseColour = { r: 0, g: 0, b: 0 };
|
||||
materialDiffuseTexturePath = ""
|
||||
break;
|
||||
|
||||
case "Kd":
|
||||
const diffuseColour = lineTokens.slice(1).map(x => parseFloat(x))
|
||||
if (!diffuseColour || diffuseColour.length != 3) {
|
||||
throw Error(`Could not parse .mtl file. (Line ${i+1})`);
|
||||
throw Error(`Could not parse .mtl file. (Line ${i + 1})`);
|
||||
}
|
||||
if (diffuseColour.some(x => Number.isNaN(x))) {
|
||||
throw Error(`Could not parse .mtl file. (Line ${i+1})`);
|
||||
throw Error(`Could not parse .mtl file. (Line ${i + 1})`);
|
||||
}
|
||||
materialDiffuseColour = {
|
||||
r: diffuseColour[0], g: diffuseColour[1], b: diffuseColour[2]
|
||||
@ -172,11 +190,11 @@ export class Mesh {
|
||||
|
||||
case "map_Kd":
|
||||
if (!lineTokens[1]) {
|
||||
throw Error(`No valid path to texture in .mtl file. (Line ${i+1})`);
|
||||
throw Error(`No valid path to texture in .mtl file. (Line ${i + 1})`);
|
||||
}
|
||||
let texturePath = lineTokens[1];
|
||||
if (!path.isAbsolute(texturePath)) {
|
||||
texturePath = path.join(this.objPath.dir, texturePath);
|
||||
texturePath = path.join(objPath.dir, texturePath);
|
||||
}
|
||||
if (!fs.existsSync(texturePath)) {
|
||||
console.error(texturePath);
|
||||
@ -202,120 +220,113 @@ export class Mesh {
|
||||
return materialsJSON;
|
||||
}
|
||||
|
||||
/*
|
||||
DISCLAIMER: This is a modified version of wavefront-obj-parser
|
||||
to include .mtl data (https://www.npmjs.com/package/wavefront-obj-parser)
|
||||
*/
|
||||
// TODO: Just re-write this whole thing, wtf have I done, these types tho
|
||||
_parseWavefrontObj(wavefrontString: string): objData {
|
||||
|
||||
const vertexInfoNameMap: {[key: string]: string} = {v: 'vertexPositions', vt: 'vertexUVs', vn: 'vertexNormals'};
|
||||
private _mergeMaterialData(parsedOBJ: ParsedOBJ, parsedMTL: Materials): Array<Material> {
|
||||
parsedOBJ.materials.forEach(material => {
|
||||
material.attachMTLData(parsedMTL[material.name]);
|
||||
});
|
||||
|
||||
var parsedJSON: {[key: string]: Array<number>} = {
|
||||
vertexNormals: [],
|
||||
vertexUVs: [],
|
||||
vertexPositions: [],
|
||||
vertexNormalIndices: [],
|
||||
vertexUVIndices: [],
|
||||
vertexPositionIndices: [],
|
||||
};
|
||||
var vertexMaterial: Array<string> = [];
|
||||
return parsedOBJ.materials;
|
||||
}
|
||||
|
||||
var linesInWavefrontObj = wavefrontString.split('\n');
|
||||
var currentMaterial: string = "";
|
||||
|
||||
// Loop through and parse every line in our .obj file
|
||||
for (let i = 0; i < linesInWavefrontObj.length; i++) {
|
||||
const currentLine = linesInWavefrontObj[i];
|
||||
// Tokenize our current line
|
||||
const currentLineTokens = currentLine.trim().split(/\s+/);
|
||||
// vertex position, vertex texture, or vertex normal
|
||||
const vertexInfoType = vertexInfoNameMap[currentLineTokens[0]];
|
||||
private _parseOBJFile(wavefrontString: string): ParsedOBJ {
|
||||
const lines = wavefrontString.split("\n");
|
||||
|
||||
if (vertexInfoType) {
|
||||
for (let k = 1; k < currentLineTokens.length; k++) {
|
||||
parsedJSON[vertexInfoType].push(parseFloat(currentLineTokens[k]));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let mtlPath: (string | undefined);
|
||||
|
||||
switch (currentLineTokens[0]) {
|
||||
let vertexPositionMap: VertexMap<Vector3> = {};
|
||||
let vertexTexcoordMap: VertexMap<UV> = {};
|
||||
let vertexNormalMap: VertexMap<Vector3> = {};
|
||||
|
||||
let vertexPositionIndex = 1;
|
||||
let vertexTexcoordIndex = 1;
|
||||
let vertexNormalIndex = 1;
|
||||
|
||||
let currentMaterial: Material = new Material("");
|
||||
let materials: Array<Material> = [];
|
||||
|
||||
lines.forEach(line => {
|
||||
const tokens = line.split(" ");
|
||||
switch (tokens[0]) {
|
||||
case "mtllib":
|
||||
this.mtlPath = currentLineTokens[1];
|
||||
mtlPath = tokens[1];
|
||||
break;
|
||||
case "v":
|
||||
vertexPositionMap[vertexPositionIndex++] = Vector3.parse(tokens[1], tokens[2], tokens[3]);
|
||||
break;
|
||||
case "vn":
|
||||
vertexNormalMap[vertexNormalIndex++] = Vector3.parse(tokens[1], tokens[2], tokens[3]);
|
||||
break;
|
||||
case "vt":
|
||||
vertexTexcoordMap[vertexTexcoordIndex++] = { u: parseFloat(tokens[1]), v: parseFloat(tokens[2]) };
|
||||
break;
|
||||
case "usemtl":
|
||||
currentMaterial = currentLineTokens[1];
|
||||
if (currentMaterial.isFilled()) {
|
||||
materials.push(currentMaterial);
|
||||
}
|
||||
currentMaterial = new Material(tokens[1]);
|
||||
break;
|
||||
case "f":
|
||||
// Get our 4 sets of vertex, uv, and normal indices for this face
|
||||
for (let k = 1; k < 5; k++) {
|
||||
// If there is no fourth face entry then this is specifying a triangle
|
||||
// in this case we push `-1`
|
||||
// Consumers of this module should check for `-1` before expanding face data
|
||||
if (k === 4 && !currentLineTokens[4]) {
|
||||
parsedJSON.vertexPositionIndices.push(-1);
|
||||
parsedJSON.vertexUVIndices.push(-1);
|
||||
parsedJSON.vertexNormalIndices.push(-1);
|
||||
//parsedJSON.vertexMaterial.push(currentMaterial);
|
||||
} else {
|
||||
var indices = currentLineTokens[k].split('/');
|
||||
parsedJSON.vertexPositionIndices.push(parseInt(indices[0], 10) - 1); // We zero index
|
||||
parsedJSON.vertexUVIndices.push(parseInt(indices[1], 10) - 1); // our face indices
|
||||
parsedJSON.vertexNormalIndices.push(parseInt(indices[2], 10) - 1); // by subtracting 1
|
||||
vertexMaterial.push(currentMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
const v0 = Vertex.parseFromOBJ(tokens[1], vertexPositionMap, vertexTexcoordMap, vertexNormalMap);
|
||||
const v1 = Vertex.parseFromOBJ(tokens[2], vertexPositionMap, vertexTexcoordMap, vertexNormalMap);
|
||||
const v2 = Vertex.parseFromOBJ(tokens[3], vertexPositionMap, vertexTexcoordMap, vertexNormalMap);
|
||||
|
||||
const face = new Triangle(v0, v1, v2);
|
||||
currentMaterial.addFace(face);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (currentMaterial.isFilled()) {
|
||||
materials.push(currentMaterial);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
vertexNormals: parsedJSON["vertexNormals"],
|
||||
vertexUVs: parsedJSON["vertexUVs"],
|
||||
vertexPositions: parsedJSON["vertexPositions"],
|
||||
vertexNormalIndices: parsedJSON["vertexNormalIndices"],
|
||||
vertexUVIndices: parsedJSON["vertexUVIndices"],
|
||||
vertexPositionIndices: parsedJSON["vertexPositionIndices"],
|
||||
vertexMaterial: vertexMaterial
|
||||
mtlPath: mtlPath,
|
||||
materials: materials
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Factor in triagle's size, perform weighted sum
|
||||
|
||||
// TODO: Factor in triangle's size, perform weighted sum
|
||||
// to prevent areas of dense triangles dominating
|
||||
private _centreMesh() {
|
||||
// Find the centre
|
||||
let centre = new Vector3(0, 0, 0);
|
||||
let count = 0;
|
||||
this.materialTriangles.forEach(materialTriangle => {
|
||||
materialTriangle.triangles.forEach(triangle => {
|
||||
centre.add(triangle.getCentre());
|
||||
this.materials.forEach(material => {
|
||||
material.faces.forEach(face => {
|
||||
centre.add(face.getCentre());
|
||||
++count;
|
||||
});
|
||||
});
|
||||
centre.divScalar(count);
|
||||
console.log(centre);
|
||||
|
||||
// Translate each triangle
|
||||
this.materialTriangles.forEach(materialTriangle => {
|
||||
materialTriangle.triangles.forEach(triangle => {
|
||||
triangle.v0.sub(centre);
|
||||
triangle.v1.sub(centre);
|
||||
triangle.v2.sub(centre);
|
||||
triangle.buildAABB();
|
||||
this.materials.forEach(material => {
|
||||
material.faces.forEach(face => {
|
||||
face.v0.position = Vector3.sub(face.v0.position, centre);
|
||||
face.v1.position = Vector3.sub(face.v1.position, centre);
|
||||
face.v2.position = Vector3.sub(face.v2.position, centre);
|
||||
face.updateAABB();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (Optional) Scale model so each imported model is the same size
|
||||
* Scale model so each imported model is the same size
|
||||
*/
|
||||
private _normaliseMesh() {
|
||||
// Find the size
|
||||
let a = new Vector3( Infinity, Infinity, Infinity);
|
||||
let a = new Vector3(Infinity, Infinity, Infinity);
|
||||
let b = new Vector3(-Infinity, -Infinity, -Infinity);
|
||||
this.materialTriangles.forEach(materialTriangle => {
|
||||
materialTriangle.triangles.forEach(triangle => {
|
||||
const aabb = triangle.getAABB();
|
||||
|
||||
this.materials.forEach(material => {
|
||||
material.faces.forEach(face => {
|
||||
const aabb = face.getAABB();
|
||||
a.x = Math.min(a.x, aabb.a.x);
|
||||
a.y = Math.min(a.y, aabb.a.y);
|
||||
a.z = Math.min(a.z, aabb.a.z);
|
||||
@ -328,63 +339,27 @@ export class Mesh {
|
||||
const size = Vector3.sub(b, a);
|
||||
const targetSize = 8.0;
|
||||
const scaleFactor = targetSize / Math.max(size.x, size.y, size.z);
|
||||
|
||||
|
||||
// Scale each triangle
|
||||
this.materialTriangles.forEach(materialTriangle => {
|
||||
materialTriangle.triangles.forEach(triangle => {
|
||||
triangle.v0.mulScalar(scaleFactor);
|
||||
triangle.v1.mulScalar(scaleFactor);
|
||||
triangle.v2.mulScalar(scaleFactor);
|
||||
triangle.buildAABB();
|
||||
this.materials.forEach(material => {
|
||||
material.faces.forEach(face => {
|
||||
face.v0.position.mulScalar(scaleFactor);
|
||||
face.v1.position.mulScalar(scaleFactor);
|
||||
face.v2.position.mulScalar(scaleFactor);
|
||||
face.updateAABB();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_parseTriangles(materials: Materials) {
|
||||
this.materialTriangles = [];
|
||||
|
||||
for (const materialName in this._materialIndices) {
|
||||
let triangles = [];
|
||||
const indices = this._materialIndices[materialName];
|
||||
|
||||
for (let i = 0; i < indices.length; i += 3) {
|
||||
const i0 = indices[i];
|
||||
const i1 = indices[i + 1];
|
||||
const i2 = indices[i + 2];
|
||||
|
||||
const v0 = this._data.position.slice(3 * i0, 3 * i0 + 3);
|
||||
const v1 = this._data.position.slice(3 * i1, 3 * i1 + 3);
|
||||
const v2 = this._data.position.slice(3 * i2, 3 * i2 + 3);
|
||||
|
||||
const uv0 = this._data.texcoord.slice(2 * i0, 2 * i0 + 2);
|
||||
const uv1 = this._data.texcoord.slice(2 * i1, 2 * i1 + 2);
|
||||
const uv2 = this._data.texcoord.slice(2 * i2, 2 * i2 + 2);
|
||||
|
||||
const v0_ = new Vector3(v0[0], v0[1], v0[2]);
|
||||
const v1_ = new Vector3(v1[0], v1[1], v1[2]);
|
||||
const v2_ = new Vector3(v2[0], v2[1], v2[2]);
|
||||
|
||||
triangles.push(new Triangle(v0_, v1_, v2_, {u: uv0[0], v: uv0[1]}, {u: uv1[0], v: uv1[1]}, {u: uv2[0], v: uv2[1]}));
|
||||
}
|
||||
|
||||
this.materialTriangles.push({
|
||||
material: materials[materialName],
|
||||
triangles: triangles
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_loadTextures(materials: Materials) {
|
||||
for (const materialName in materials) {
|
||||
if (materials[materialName].type == MaterialType.Texture) {
|
||||
const material = <TextureMaterial> materials[materialName];
|
||||
material.texture = twgl.createTexture(this._gl, {
|
||||
src: material.texturePath,
|
||||
mag: this._gl.LINEAR
|
||||
public loadTextures(gl: WebGLRenderingContext) {
|
||||
this.materials.forEach(material => {
|
||||
if (material.materialData?.type === MaterialType.Texture) {
|
||||
material.materialData.texture = twgl.createTexture(gl, {
|
||||
src: material.materialData.texturePath,
|
||||
mag: gl.LINEAR
|
||||
});
|
||||
materials[materialName] = material;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
134
src/renderer.ts
134
src/renderer.ts
@ -15,8 +15,8 @@ import { Mesh, FillMaterial, TextureMaterial, MaterialType } from "./mesh";
|
||||
|
||||
export class Renderer {
|
||||
|
||||
private _backgroundColour: RGB = {r: 0.1, g: 0.1, b: 0.1};
|
||||
private _strokeColour: RGB = {r: 1.0, g: 0.0, b: 0.0};
|
||||
private _backgroundColour: RGB = { r: 0.1, g: 0.1, b: 0.1 };
|
||||
private _strokeColour: RGB = { r: 1.0, g: 0.0, b: 0.0 };
|
||||
private _fov: number = 30;
|
||||
private _gl: WebGLRenderingContext;
|
||||
private _camera: ArcballCamera;
|
||||
@ -50,7 +50,7 @@ export class Renderer {
|
||||
this._compiled = false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//this._blockTexture = twgl.createTexture(this._gl, { src: "resources/blocks/stone.png", mag: this._gl.NEAREST });
|
||||
this._materialBuffers = [];
|
||||
@ -59,10 +59,10 @@ export class Renderer {
|
||||
src: path.join(__dirname, "../resources/blocks.png"),
|
||||
mag: this._gl.NEAREST
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public set strokeColour(colour: RGB) {
|
||||
@ -78,13 +78,13 @@ export class Renderer {
|
||||
this._registerData(data);
|
||||
}
|
||||
|
||||
private _registerVoxel(centre: Vector3, voxelManager: VoxelManager, blockTexcoord: UV) {
|
||||
let occlusions = new Array<Array<number>>(6);
|
||||
private _registerVoxel(centre: Vector3, voxelManager: VoxelManager, blockTexcoord: UV) {
|
||||
let occlusions = new Array<Array<number>>(6);
|
||||
// For each face
|
||||
for (let f = 0; f < 6; ++f) {
|
||||
// For each vertex
|
||||
occlusions[f] = [0, 0, 0, 0];
|
||||
|
||||
|
||||
for (let v = 0; v < 4; ++v) {
|
||||
// For each occlusion vertex
|
||||
for (let o = 0; o < 3; ++o) {
|
||||
@ -94,7 +94,7 @@ export class Renderer {
|
||||
|
||||
// Convert from occlusion denoting the occlusion factor to the
|
||||
// attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4
|
||||
occlusions[f] = occlusions[f].map(x => 1.0 - 0.2 * x);
|
||||
occlusions[f] = occlusions[f].map(x => 1.0 - 0.2 * x);
|
||||
}
|
||||
|
||||
let data: VoxelData = GeometryTemplates.getBoxBufferData(centre, false);
|
||||
@ -121,29 +121,27 @@ export class Renderer {
|
||||
this._registerData(data);
|
||||
}
|
||||
|
||||
public registerMesh(mesh: Mesh) {
|
||||
for (const material in mesh.materialTriangles) {
|
||||
public registerMesh(mesh: Mesh) {
|
||||
//console.log(mesh);
|
||||
|
||||
mesh.materials.forEach(material => {
|
||||
const materialBuffer = new BottomlessBuffer([
|
||||
{name: 'position', numComponents: 3},
|
||||
{name: 'texcoord', numComponents: 2},
|
||||
{name: 'normal', numComponents: 3}
|
||||
{ name: 'position', numComponents: 3 },
|
||||
{ name: 'texcoord', numComponents: 2 },
|
||||
{ name: 'normal', numComponents: 3 }
|
||||
]);
|
||||
const materialTriangles = mesh.materialTriangles[material];
|
||||
console.log(materialTriangles);
|
||||
materialTriangles.triangles.forEach(triangle => {
|
||||
const data = GeometryTemplates.getTriangleBufferData(triangle, false);
|
||||
|
||||
material.faces.forEach(face => {
|
||||
const data = GeometryTemplates.getTriangleBufferData(face, false);
|
||||
//console.log(data);
|
||||
materialBuffer.add(data);
|
||||
});
|
||||
|
||||
this._materialBuffers.push({
|
||||
buffer: materialBuffer,
|
||||
material: materialTriangles.material
|
||||
material: material.materialData
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
console.log("MATERIAL BUFFERS:", this._materialBuffers);
|
||||
});
|
||||
}
|
||||
|
||||
registerVoxelMesh(voxelManager: VoxelManager) {
|
||||
@ -156,8 +154,8 @@ export class Renderer {
|
||||
this.registerBox(voxel.position);
|
||||
});
|
||||
} else {
|
||||
// Setup arrays for calculating voxel ambient occlusion
|
||||
|
||||
// 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];
|
||||
@ -170,7 +168,7 @@ export class Renderer {
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
const mesh = voxelManager.buildMesh();
|
||||
for (const box of mesh) {
|
||||
@ -215,7 +213,7 @@ export class Renderer {
|
||||
u_texture: this._atlasTexture,
|
||||
u_voxelSize: voxelSize
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
// Draw default register
|
||||
this._drawRegister(this._registerDefault, this._gl.TRIANGLES, shaderManager.shadedProgram, {
|
||||
@ -256,45 +254,45 @@ export class Renderer {
|
||||
|
||||
this._occlusionNeighbours = [
|
||||
[
|
||||
[new Vector3( 1, 1, 0), new Vector3( 1, 1, -1), new Vector3( 1, 0, -1)],
|
||||
[new Vector3( 1, -1, 0), new Vector3( 1, -1, -1), new Vector3( 1, 0, -1)],
|
||||
[new Vector3( 1, 1, 0), new Vector3( 1, 1, 1), new Vector3( 1, 0, 1)],
|
||||
[new Vector3( 1, -1, 0), new Vector3( 1, -1, 1), new Vector3( 1, 0, 1)]
|
||||
[new Vector3(1, 1, 0), new Vector3(1, 1, -1), new Vector3(1, 0, -1)],
|
||||
[new Vector3(1, -1, 0), new Vector3(1, -1, -1), new Vector3(1, 0, -1)],
|
||||
[new Vector3(1, 1, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 1)],
|
||||
[new Vector3(1, -1, 0), new Vector3(1, -1, 1), new Vector3(1, 0, 1)]
|
||||
],
|
||||
|
||||
[
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, -1), new Vector3(-1, 0, -1)]
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, -1), new Vector3(-1, 0, -1)]
|
||||
],
|
||||
|
||||
[
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, 1), new Vector3( 0, 1, 1)],
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, -1), new Vector3( 0, 1, -1)],
|
||||
[new Vector3( 1, 1, 0), new Vector3( 1, 1, 1), new Vector3( 0, 1, 1)],
|
||||
[new Vector3( 1, 1, 0), new Vector3( 1, 1, -1), new Vector3( 0, 1, -1)]
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, 1), new Vector3(0, 1, 1)],
|
||||
[new Vector3(-1, 1, 0), new Vector3(-1, 1, -1), new Vector3(0, 1, -1)],
|
||||
[new Vector3(1, 1, 0), new Vector3(1, 1, 1), new Vector3(0, 1, 1)],
|
||||
[new Vector3(1, 1, 0), new Vector3(1, 1, -1), new Vector3(0, 1, -1)]
|
||||
],
|
||||
|
||||
[
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, -1), new Vector3( 0, -1, -1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, 1), new Vector3( 0, -1, 1)],
|
||||
[new Vector3( 1, -1, 0), new Vector3( 1, -1, -1), new Vector3( 0, -1, -1)],
|
||||
[new Vector3( 1, -1, 0), new Vector3( 1, -1, 1), new Vector3( 0, -1, 1)]
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, -1), new Vector3(0, -1, -1)],
|
||||
[new Vector3(-1, -1, 0), new Vector3(-1, -1, 1), new Vector3(0, -1, 1)],
|
||||
[new Vector3(1, -1, 0), new Vector3(1, -1, -1), new Vector3(0, -1, -1)],
|
||||
[new Vector3(1, -1, 0), new Vector3(1, -1, 1), new Vector3(0, -1, 1)]
|
||||
],
|
||||
|
||||
[
|
||||
[new Vector3( 0, 1, 1), new Vector3( 1, 1, 1), new Vector3( 1, 0, 1)],
|
||||
[new Vector3( 0, -1, 1), new Vector3( 1, -1, 1), new Vector3( 1, 0, 1)],
|
||||
[new Vector3( 0, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3( 0, -1, 1), new Vector3(-1, -1, 1), new Vector3(-1, 0, 1)]
|
||||
[new Vector3(0, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 0, 1)],
|
||||
[new Vector3(0, -1, 1), new Vector3(1, -1, 1), new Vector3(1, 0, 1)],
|
||||
[new Vector3(0, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 0, 1)],
|
||||
[new Vector3(0, -1, 1), new Vector3(-1, -1, 1), new Vector3(-1, 0, 1)]
|
||||
],
|
||||
|
||||
[
|
||||
[new Vector3( 0, 1, -1), new Vector3(-1, 1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3( 0, -1, -1), new Vector3(-1, -1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3( 0, 1, -1), new Vector3( 1, 1, -1), new Vector3( 1, 0, -1)],
|
||||
[new Vector3( 0, -1, -1), new Vector3( 1, -1, -1), new Vector3( 1, 0, -1)]
|
||||
[new Vector3(0, 1, -1), new Vector3(-1, 1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3(0, -1, -1), new Vector3(-1, -1, -1), new Vector3(-1, 0, -1)],
|
||||
[new Vector3(0, 1, -1), new Vector3(1, 1, -1), new Vector3(1, 0, -1)],
|
||||
[new Vector3(0, -1, -1), new Vector3(1, -1, -1), new Vector3(1, 0, -1)]
|
||||
]
|
||||
]
|
||||
}
|
||||
@ -306,7 +304,7 @@ export class Renderer {
|
||||
this._registerDebug.add(data);
|
||||
} else {
|
||||
this._registerDefault.add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setupScene() {
|
||||
@ -314,36 +312,36 @@ export class Renderer {
|
||||
this._gl.viewport(0, 0, this._gl.canvas.width, this._gl.canvas.height);
|
||||
this._camera.aspect = this._gl.canvas.width / this._gl.canvas.height;
|
||||
this._gl.blendFuncSeparate(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
this._gl.enable(this._gl.DEPTH_TEST);
|
||||
//this._gl.enable(this._gl.CULL_FACE);
|
||||
this._gl.enable(this._gl.BLEND);
|
||||
this._gl.clearColor(this._backgroundColour.r, this._backgroundColour.g, this._backgroundColour.b, 1.0);
|
||||
this._gl.clear(this._gl.COLOR_BUFFER_BIT | this._gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
this._camera.updateCameraPosition();
|
||||
this._camera.updateCameraPosition();
|
||||
}
|
||||
|
||||
_registerEvents() {
|
||||
this._gl.canvas.addEventListener('mousedown', (e) => {
|
||||
this._camera.isRotating = true;
|
||||
});
|
||||
|
||||
|
||||
this._gl.canvas.addEventListener('mouseup', (e) => {
|
||||
this._camera.isRotating = false;
|
||||
});
|
||||
|
||||
|
||||
this._gl.canvas.addEventListener('mousemove', (e) => {
|
||||
this._mouseManager.handleInput(<MouseEvent>e);
|
||||
this._camera.updateCamera(this._mouseManager.getMouseDelta());
|
||||
});
|
||||
|
||||
|
||||
this._gl.canvas.addEventListener('wheel', (e) => {
|
||||
this._camera.handleScroll(<WheelEvent>e);
|
||||
});
|
||||
}
|
||||
|
||||
_drawBuffer(drawMode: number, buffer: {numElements: number, buffer: twgl.BufferInfo}, shader: twgl.ProgramInfo, uniforms: any) {
|
||||
_drawBuffer(drawMode: number, buffer: { numElements: number, buffer: twgl.BufferInfo }, shader: twgl.ProgramInfo, uniforms: any) {
|
||||
this._gl.useProgram(shader.program);
|
||||
twgl.setBuffersAndAttributes(this._gl, shader, buffer.buffer);
|
||||
twgl.setUniforms(shader, uniforms);
|
||||
@ -353,20 +351,20 @@ export class Renderer {
|
||||
_getNewBuffers() {
|
||||
const bufferSize = 16384 * 16;
|
||||
this._registerDebug = new SegmentedBuffer(bufferSize, [
|
||||
{name: 'position', numComponents: 3, insertIndex: 0},
|
||||
{name: 'colour', numComponents: 3, insertIndex: 0}
|
||||
{ name: 'position', numComponents: 3, insertIndex: 0 },
|
||||
{ name: 'colour', numComponents: 3, insertIndex: 0 }
|
||||
]);
|
||||
this._registerVoxels = new SegmentedBuffer(bufferSize, [
|
||||
{name: 'position', numComponents: 3, insertIndex: 0},
|
||||
{name: 'normal', numComponents: 3, insertIndex: 0},
|
||||
{name: 'occlusion', numComponents: 4, insertIndex: 0},
|
||||
{name: 'texcoord', numComponents: 2, insertIndex: 0},
|
||||
{name: 'blockTexcoord', numComponents: 2, insertIndex: 0},
|
||||
{ name: 'position', numComponents: 3, insertIndex: 0 },
|
||||
{ name: 'normal', numComponents: 3, insertIndex: 0 },
|
||||
{ name: 'occlusion', numComponents: 4, insertIndex: 0 },
|
||||
{ name: 'texcoord', numComponents: 2, insertIndex: 0 },
|
||||
{ name: 'blockTexcoord', numComponents: 2, insertIndex: 0 },
|
||||
]);
|
||||
this._registerDefault = new SegmentedBuffer(bufferSize, [
|
||||
{name: 'position', numComponents: 3, insertIndex: 0},
|
||||
{ name: 'position', numComponents: 3, insertIndex: 0 },
|
||||
//{name: 'colour', numComponents: 3},
|
||||
{name: 'normal', numComponents: 3, insertIndex: 0}
|
||||
{ name: 'normal', numComponents: 3, insertIndex: 0 }
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,11 @@ import * as fs from "fs";
|
||||
import * as jpeg from "jpeg-js";
|
||||
import { PNG } from "pngjs";
|
||||
import { UV, RGBA } from "./util";
|
||||
import { TextureFormat } from "./mesh";
|
||||
|
||||
export enum TextureFormat {
|
||||
PNG,
|
||||
JPEG
|
||||
}
|
||||
|
||||
export class Texture {
|
||||
|
||||
|
@ -2,48 +2,40 @@ import { Vector3 } from "./vector";
|
||||
import { AABB } from "./aabb";
|
||||
import { xAxis, yAxis, zAxis, fastCrossXAxis, fastCrossYAxis, fastCrossZAxis } from "./math";
|
||||
import { UV } from "./util";
|
||||
import { Vertex } from "./mesh";
|
||||
|
||||
|
||||
export class Triangle {
|
||||
|
||||
public v0: Vector3;
|
||||
public v1: Vector3;
|
||||
public v2: Vector3;
|
||||
public v0: Vertex;
|
||||
public v1: Vertex;
|
||||
public v2: Vertex;
|
||||
public readonly normal: Vector3;
|
||||
|
||||
public readonly uv0: UV;
|
||||
public readonly uv1: UV;
|
||||
public readonly uv2: UV;
|
||||
private aabb?: AABB;
|
||||
|
||||
private aabb!: AABB;
|
||||
|
||||
constructor(v0: Vector3, v1: Vector3, v2: Vector3, uv0: UV, uv1: UV, uv2: UV) {
|
||||
constructor(v0: Vertex, v1: Vertex, v2: Vertex) {
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
|
||||
this.uv0 = uv0;
|
||||
this.uv1 = uv1;
|
||||
this.uv2 = uv2;
|
||||
|
||||
const f0 = Vector3.sub(v1, v0);
|
||||
const f1 = Vector3.sub(v0, v2);
|
||||
const f0 = Vector3.sub(v1.position, v0.position);
|
||||
const f1 = Vector3.sub(v0.position, v2.position);
|
||||
this.normal = Vector3.cross(f0, f1).normalise();
|
||||
|
||||
this.buildAABB();
|
||||
this.updateAABB();
|
||||
}
|
||||
|
||||
public buildAABB() {
|
||||
public updateAABB() {
|
||||
const a = new Vector3(
|
||||
Math.min(this.v0.x, this.v1.x, this.v2.x),
|
||||
Math.min(this.v0.y, this.v1.y, this.v2.y),
|
||||
Math.min(this.v0.z, this.v1.z, this.v2.z)
|
||||
Math.min(this.v0.position.x, this.v1.position.x, this.v2.position.x),
|
||||
Math.min(this.v0.position.y, this.v1.position.y, this.v2.position.y),
|
||||
Math.min(this.v0.position.z, this.v1.position.z, this.v2.position.z)
|
||||
);
|
||||
|
||||
const b = new Vector3(
|
||||
Math.max(this.v0.x, this.v1.x, this.v2.x),
|
||||
Math.max(this.v0.y, this.v1.y, this.v2.y),
|
||||
Math.max(this.v0.z, this.v1.z, this.v2.z)
|
||||
Math.max(this.v0.position.x, this.v1.position.x, this.v2.position.x),
|
||||
Math.max(this.v0.position.y, this.v1.position.y, this.v2.position.y),
|
||||
Math.max(this.v0.position.z, this.v1.position.z, this.v2.position.z)
|
||||
);
|
||||
|
||||
const centre = Vector3.mulScalar(Vector3.add(a, b), 0.5);
|
||||
@ -53,19 +45,19 @@ export class Triangle {
|
||||
}
|
||||
|
||||
public getAABB() {
|
||||
return this.aabb;
|
||||
return this.aabb!;
|
||||
}
|
||||
|
||||
public insideAABB(aabb: AABB) {
|
||||
return Vector3.lessThanEqualTo(aabb.a, this.aabb.a) && Vector3.lessThanEqualTo(this.aabb.b, aabb.b);
|
||||
return Vector3.lessThanEqualTo(aabb.a, this.aabb!.a) && Vector3.lessThanEqualTo(this.aabb!.b, aabb.b);
|
||||
}
|
||||
|
||||
public intersectAABB(aabb: AABB) {
|
||||
const extents = Vector3.mulScalar(aabb.size, 0.5);
|
||||
|
||||
const v0 = Vector3.sub(this.v0, aabb.centre);
|
||||
const v1 = Vector3.sub(this.v1, aabb.centre);
|
||||
const v2 = Vector3.sub(this.v2, aabb.centre);
|
||||
const v0 = Vector3.sub(this.v0.position, aabb.centre);
|
||||
const v1 = Vector3.sub(this.v1.position, aabb.centre);
|
||||
const v2 = Vector3.sub(this.v2.position, aabb.centre);
|
||||
|
||||
const f0 = Vector3.sub(v1, v0);
|
||||
const f1 = Vector3.sub(v2, v1);
|
||||
@ -96,10 +88,11 @@ export class Triangle {
|
||||
return true;
|
||||
}
|
||||
|
||||
public getCentre() {
|
||||
return Vector3.divScalar(Vector3.add(Vector3.add(this.v0, this.v1), this.v2), 3.0);
|
||||
public getCentre(): Vector3 {
|
||||
return Vector3.divScalar(Vector3.add(Vector3.add(this.v0.position, this.v1.position), this.v2.position), 3.0);
|
||||
}
|
||||
|
||||
|
||||
private _testAxis(v0: Vector3, v1: Vector3, v2: Vector3, axis: Vector3, extents: Vector3) {
|
||||
let p0 = Vector3.dot(v0, axis);
|
||||
let p1 = Vector3.dot(v1, axis);
|
||||
|
@ -25,6 +25,14 @@ export class Vector3 extends Hashable {
|
||||
);
|
||||
}
|
||||
|
||||
static parse(f1: string, f2: string, f3: string) {
|
||||
return new Vector3(
|
||||
parseFloat(f1),
|
||||
parseFloat(f2),
|
||||
parseFloat(f3)
|
||||
)
|
||||
}
|
||||
|
||||
add(vec: Vector3) {
|
||||
this.x += vec.x;
|
||||
this.y += vec.y;
|
||||
|
@ -313,9 +313,9 @@ export class VoxelManager {
|
||||
return this._currentColour;
|
||||
}
|
||||
|
||||
let distV0 = Vector3.sub(triangle.v0, centre).magnitude();
|
||||
let distV1 = Vector3.sub(triangle.v1, centre).magnitude();
|
||||
let distV2 = Vector3.sub(triangle.v2, centre).magnitude();
|
||||
let distV0 = Vector3.sub(triangle.v0.position, centre).magnitude();
|
||||
let distV1 = Vector3.sub(triangle.v1.position, centre).magnitude();
|
||||
let distV2 = Vector3.sub(triangle.v2.position, centre).magnitude();
|
||||
|
||||
const k = distV0 + distV1 + distV2;
|
||||
distV0 /= k;
|
||||
@ -323,8 +323,8 @@ export class VoxelManager {
|
||||
distV2 /= k;
|
||||
|
||||
const uv = {
|
||||
u: triangle.uv0.u * distV0 + triangle.uv1.u * distV1 + triangle.uv2.u * distV2,
|
||||
v: triangle.uv0.v * distV0 + triangle.uv1.v * distV1 + triangle.uv2.v * distV2,
|
||||
u: triangle.v0.texcoord.u * distV0 + triangle.v1.texcoord.u * distV1 + triangle.v2.texcoord.u * distV2,
|
||||
v: triangle.v0.texcoord.v * distV0 + triangle.v1.texcoord.v * distV1 + triangle.v2.texcoord.v * distV2,
|
||||
}
|
||||
|
||||
return this._currentTexture.getRGBA(uv);
|
||||
@ -398,23 +398,25 @@ export class VoxelManager {
|
||||
}
|
||||
|
||||
voxeliseMesh(mesh: Mesh) {
|
||||
for (const materialName in mesh.materialTriangles) {
|
||||
const materialTriangles = mesh.materialTriangles[materialName];
|
||||
mesh.materials.forEach(material => {
|
||||
// Setup material
|
||||
if (materialTriangles.material.type === MaterialType.Texture) {
|
||||
console.log("VOXELISING", material.name);
|
||||
|
||||
if (material.materialData?.type === MaterialType.Texture) {
|
||||
this._blockMode = MaterialType.Texture;
|
||||
this._currentTexture = new Texture(materialTriangles.material.texturePath, materialTriangles.material.format);
|
||||
this._currentTexture = new Texture(material.materialData.texturePath, material.materialData.format);
|
||||
} else {
|
||||
this._currentColour = materialTriangles.material.diffuseColour;
|
||||
this._currentColour = material.materialData!.diffuseColour;
|
||||
this._blockMode = MaterialType.Fill;
|
||||
}
|
||||
// Handle triangles
|
||||
for (const triangle of materialTriangles.triangles) {
|
||||
this.voxeliseTriangle(triangle);
|
||||
}
|
||||
}
|
||||
material.faces.forEach(face => {
|
||||
console.log("FACE");
|
||||
this.voxeliseTriangle(face);
|
||||
});
|
||||
});
|
||||
|
||||
this.assignBlocks();
|
||||
console.log(this.blockPalette);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user