mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2024-12-15 02:59:55 +08:00
Added JPEG support
This commit is contained in:
parent
a03e3632d5
commit
62cde694dc
@ -29,6 +29,7 @@ A tool to convert .obj files into Minecraft Schematics.
|
|||||||
* ✔️ **Quality of life**
|
* ✔️ **Quality of life**
|
||||||
* ✔️ Model PSR, ✔️ voxel size preview ✔️ limit warnings
|
* ✔️ Model PSR, ✔️ voxel size preview ✔️ limit warnings
|
||||||
* ✔️ **.mtl support for block choice**
|
* ✔️ **.mtl support for block choice**
|
||||||
|
* ✔️ PNG support, ✔️ JPEG support
|
||||||
* ✔️ **Convert to TypeScript**
|
* ✔️ **Convert to TypeScript**
|
||||||
* ⌛ Block choice exported
|
* ⌛ Block choice exported
|
||||||
|
|
||||||
|
28
src/mesh.ts
28
src/mesh.ts
@ -7,7 +7,12 @@ const expandVertexData: any = require("expand-vertex-data");
|
|||||||
import { Triangle } from "./triangle";
|
import { Triangle } from "./triangle";
|
||||||
import { Vector3 } from "./vector";
|
import { Vector3 } from "./vector";
|
||||||
import { RGB } from "./util";
|
import { RGB } from "./util";
|
||||||
|
import { Texture } from "./texture";
|
||||||
|
|
||||||
|
export enum TextureFormat {
|
||||||
|
PNG,
|
||||||
|
JPEG
|
||||||
|
}
|
||||||
|
|
||||||
interface objData {
|
interface objData {
|
||||||
vertexNormals: Array<number>;
|
vertexNormals: Array<number>;
|
||||||
@ -31,7 +36,8 @@ export interface FillMaterial {
|
|||||||
export interface TextureMaterial {
|
export interface TextureMaterial {
|
||||||
readonly type: MaterialType.Texture
|
readonly type: MaterialType.Texture
|
||||||
texturePath: string,
|
texturePath: string,
|
||||||
texture?: WebGLTexture
|
texture?: WebGLTexture,
|
||||||
|
format: TextureFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MaterialType {
|
export enum MaterialType {
|
||||||
@ -112,12 +118,13 @@ export class Mesh {
|
|||||||
this._loadTextures(materials);
|
this._loadTextures(materials);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addMaterial(materialsJSON: Materials, materialName: string, materialDiffuseColour: RGB, materialDiffuseTexturePath: string) {
|
private _addMaterial(materialsJSON: Materials, materialName: string, materialDiffuseColour: RGB, materialDiffuseTexturePath: string, materialFormat: TextureFormat) {
|
||||||
console.log(materialName, materialDiffuseColour, materialDiffuseTexturePath);
|
console.log(materialName, materialDiffuseColour, materialDiffuseTexturePath);
|
||||||
if (materialDiffuseTexturePath !== "") {
|
if (materialDiffuseTexturePath !== "") {
|
||||||
materialsJSON[materialName] = {
|
materialsJSON[materialName] = {
|
||||||
texturePath: materialDiffuseTexturePath,
|
texturePath: materialDiffuseTexturePath,
|
||||||
type: MaterialType.Texture
|
type: MaterialType.Texture,
|
||||||
|
format: materialFormat
|
||||||
};
|
};
|
||||||
} else if (materialName !== "") {
|
} else if (materialName !== "") {
|
||||||
materialsJSON[materialName] = {
|
materialsJSON[materialName] = {
|
||||||
@ -127,6 +134,7 @@ export class Mesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Rewrite
|
||||||
private _parseMaterial(materialString: string): Materials {
|
private _parseMaterial(materialString: string): Materials {
|
||||||
var materialsJSON: Materials = {};
|
var materialsJSON: Materials = {};
|
||||||
|
|
||||||
@ -135,6 +143,7 @@ export class Mesh {
|
|||||||
let materialName: string = "";
|
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 materialDiffuseTexturePath: string = "";
|
||||||
|
let materialTextureFormat: TextureFormat = TextureFormat.PNG;
|
||||||
|
|
||||||
for (let i = 0; i < lines.length; ++i) {
|
for (let i = 0; i < lines.length; ++i) {
|
||||||
const line = lines[i];
|
const line = lines[i];
|
||||||
@ -142,7 +151,7 @@ export class Mesh {
|
|||||||
|
|
||||||
switch (lineTokens[0]) {
|
switch (lineTokens[0]) {
|
||||||
case "newmtl":
|
case "newmtl":
|
||||||
this._addMaterial(materialsJSON, materialName, materialDiffuseColour, materialDiffuseTexturePath);
|
this._addMaterial(materialsJSON, materialName, materialDiffuseColour, materialDiffuseTexturePath, materialTextureFormat);
|
||||||
materialName = lineTokens[1];
|
materialName = lineTokens[1];
|
||||||
materialDiffuseColour = {r: 0, g: 0, b: 0};
|
materialDiffuseColour = {r: 0, g: 0, b: 0};
|
||||||
materialDiffuseTexturePath = ""
|
materialDiffuseTexturePath = ""
|
||||||
@ -174,8 +183,13 @@ export class Mesh {
|
|||||||
throw Error(`Cannot load texture ${texturePath}`);
|
throw Error(`Cannot load texture ${texturePath}`);
|
||||||
}
|
}
|
||||||
const _path = path.parse(texturePath);
|
const _path = path.parse(texturePath);
|
||||||
if (_path.ext.toLowerCase() != ".png") {
|
if (".png" === _path.ext.toLowerCase()) {
|
||||||
throw Error(`Can only load .png textures`);
|
materialTextureFormat = TextureFormat.PNG;
|
||||||
|
}
|
||||||
|
else if ([".jpeg", ".jpg"].includes(_path.ext.toLowerCase())) {
|
||||||
|
materialTextureFormat = TextureFormat.JPEG;
|
||||||
|
} else {
|
||||||
|
throw Error(`Can only load PNG and JPEG textures`);
|
||||||
}
|
}
|
||||||
|
|
||||||
materialDiffuseTexturePath = texturePath;
|
materialDiffuseTexturePath = texturePath;
|
||||||
@ -183,7 +197,7 @@ export class Mesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._addMaterial(materialsJSON, materialName, materialDiffuseColour, materialDiffuseTexturePath);
|
this._addMaterial(materialsJSON, materialName, materialDiffuseColour, materialDiffuseTexturePath, materialTextureFormat);
|
||||||
|
|
||||||
return materialsJSON;
|
return materialsJSON;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,31 @@
|
|||||||
//const fs = require("fs");
|
|
||||||
//const png = require("pngjs").PNG;
|
|
||||||
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { PNG, PNGWithMetadata } from "pngjs";
|
import * as jpeg from "jpeg-js";
|
||||||
|
import { PNG } from "pngjs";
|
||||||
import { UV, RGBA } from "./util";
|
import { UV, RGBA } from "./util";
|
||||||
import { clamp } from "./math";
|
import { TextureFormat } from "./mesh";
|
||||||
|
|
||||||
|
|
||||||
export class Texture {
|
export class Texture {
|
||||||
|
|
||||||
private _image: PNGWithMetadata;
|
private _image: {
|
||||||
|
data: Buffer,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
};
|
||||||
|
|
||||||
constructor(filename: string) {
|
constructor(filename: string, format: TextureFormat) {
|
||||||
try {
|
try {
|
||||||
const data = fs.readFileSync(filename);
|
const data = fs.readFileSync(filename);
|
||||||
this._image = PNG.sync.read(data);
|
if (format === TextureFormat.PNG) {
|
||||||
|
this._image = PNG.sync.read(data);
|
||||||
|
} else {
|
||||||
|
this._image = jpeg.decode(data);
|
||||||
|
}
|
||||||
|
if (this._image.width * this._image.height * 4 !== this._image.data.length) {
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw Error(`Could not read ${filename}`);
|
throw Error(`Could not parse ${filename}`);
|
||||||
}
|
|
||||||
if (this._image.bpp !== 4) {
|
|
||||||
throw Error("Image must be RBGA format");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,15 +35,14 @@ export class Texture {
|
|||||||
const x = Math.floor(uv.u * this._image.width);
|
const x = Math.floor(uv.u * this._image.width);
|
||||||
const y = Math.floor(uv.v * this._image.height);
|
const y = Math.floor(uv.v * this._image.height);
|
||||||
|
|
||||||
const index = this._image.bpp * (this._image.width * y + x);
|
const index = 4 * (this._image.width * y + x);
|
||||||
const rgba = this._image.data.slice(index, index + this._image.bpp)
|
const rgba = this._image.data.slice(index, index + 4)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
r: rgba[0]/255,
|
r: rgba[0]/255,
|
||||||
g: rgba[1]/255,
|
g: rgba[1]/255,
|
||||||
b: rgba[2]/255,
|
b: rgba[2]/255,
|
||||||
a: rgba[3]/255
|
a: 1.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { AABB, CubeAABB } from "./aabb";
|
import { CubeAABB } from "./aabb";
|
||||||
import { Vector3 } from "./vector.js";
|
import { Vector3 } from "./vector.js";
|
||||||
import { HashSet, HashMap } from "./hash_map";
|
import { HashSet } from "./hash_map";
|
||||||
import { Texture } from "./texture";
|
import { Texture } from "./texture";
|
||||||
import { BlockAtlas } from "./block_atlas";
|
import { BlockAtlas } from "./block_atlas";
|
||||||
import { UV, RGB } from "./util";
|
import { UV, RGB } from "./util";
|
||||||
@ -360,8 +360,8 @@ export class VoxelManager {
|
|||||||
const materialTriangles = mesh.materialTriangles[materialName];
|
const materialTriangles = mesh.materialTriangles[materialName];
|
||||||
// Setup material
|
// Setup material
|
||||||
if (materialTriangles.material.type === MaterialType.Texture) {
|
if (materialTriangles.material.type === MaterialType.Texture) {
|
||||||
this._currentTexture = new Texture(materialTriangles.material.texturePath);
|
|
||||||
this._blockMode = MaterialType.Texture;
|
this._blockMode = MaterialType.Texture;
|
||||||
|
this._currentTexture = new Texture(materialTriangles.material.texturePath, materialTriangles.material.format);
|
||||||
} else {
|
} else {
|
||||||
this._currentColour = materialTriangles.material.diffuseColour;
|
this._currentColour = materialTriangles.material.diffuseColour;
|
||||||
this._blockMode = MaterialType.Fill;
|
this._blockMode = MaterialType.Fill;
|
||||||
|
Loading…
Reference in New Issue
Block a user