mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2025-12-11 20:15:30 +01:00
* Added 'rotation' option when loading a model
* Fixed `voxelise` action not enabling after `import` action succeeds
This commit is contained in:
parent
57ac9dd714
commit
e4e95b0a1f
@ -188,6 +188,7 @@ export class AppContext {
|
||||
action: 'Import',
|
||||
params: {
|
||||
filepath: uiElements.input.getValue(),
|
||||
rotation: uiElements.rotation.getValue(),
|
||||
},
|
||||
};
|
||||
|
||||
@ -295,7 +296,7 @@ export class AppContext {
|
||||
const callback = (payload: TFromWorkerMessage) => {
|
||||
// This callback is not managed through `AppContext::do`, therefore
|
||||
// we need to check the payload is not an error
|
||||
this._ui.enableTo(EAction.Materials);
|
||||
this._ui.enableTo(EAction.Voxelise);
|
||||
|
||||
switch (payload.action) {
|
||||
case 'KnownError':
|
||||
|
||||
34
src/mesh.ts
34
src/mesh.ts
@ -3,6 +3,7 @@ import path from 'path';
|
||||
|
||||
import { Bounds } from './bounds';
|
||||
import { RGBA, RGBAColours, RGBAUtil } from './colour';
|
||||
import { degreesToRadians } from './math';
|
||||
import { StatusHandler } from './status';
|
||||
import { Texture, TextureConverter, TextureFiltering } from './texture';
|
||||
import { Triangle, UVTriangle } from './triangle';
|
||||
@ -81,6 +82,39 @@ export class Mesh {
|
||||
this._loadTextures();
|
||||
}
|
||||
|
||||
public rotateMesh(pitch: number, roll: number, yaw: number) {
|
||||
const cosa = Math.cos(yaw * degreesToRadians);
|
||||
const sina = Math.sin(yaw * degreesToRadians);
|
||||
|
||||
const cosb = Math.cos(pitch * degreesToRadians);
|
||||
const sinb = Math.sin(pitch * degreesToRadians);
|
||||
|
||||
const cosc = Math.cos(roll * degreesToRadians);
|
||||
const sinc = Math.sin(roll * degreesToRadians);
|
||||
|
||||
const Axx = cosa*cosb;
|
||||
const Axy = cosa*sinb*sinc - sina*cosc;
|
||||
const Axz = cosa*sinb*cosc + sina*sinc;
|
||||
|
||||
const Ayx = sina*cosb;
|
||||
const Ayy = sina*sinb*sinc + cosa*cosc;
|
||||
const Ayz = sina*sinb*cosc - cosa*sinc;
|
||||
|
||||
const Azx = -sinb;
|
||||
const Azy = cosb*sinc;
|
||||
const Azz = cosb*cosc;
|
||||
|
||||
this._vertices.forEach((vertex) => {
|
||||
const px = vertex.x;
|
||||
const py = vertex.y;
|
||||
const pz = vertex.z;
|
||||
|
||||
vertex.x = Axx * px + Axy * py + Axz * pz;
|
||||
vertex.y = Ayx * px + Ayy * py + Ayz * pz;
|
||||
vertex.z = Azx * px + Azy * py + Azz * pz;
|
||||
});
|
||||
}
|
||||
|
||||
public getBounds() {
|
||||
const bounds = Bounds.getInfiniteBounds();
|
||||
if (this._transform) {
|
||||
|
||||
@ -11,7 +11,7 @@ export class VectorSpinboxElement extends ConfigUIElement<Vector3, HTMLDivElemen
|
||||
private _showY: boolean;
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
super(new Vector3(0, 0, 0));
|
||||
this._mouseover = null;
|
||||
this._dragging = null;
|
||||
this._lastClientX = 0.0;
|
||||
@ -67,37 +67,18 @@ export class VectorSpinboxElement extends ConfigUIElement<Vector3, HTMLDivElemen
|
||||
}
|
||||
|
||||
private _registerAxis(axis: TAxis) {
|
||||
const elementKey = UIUtil.getElementById(this._getKeyId(axis));
|
||||
const elementValue = UIUtil.getElementById(this._getValueId(axis));
|
||||
|
||||
elementKey.onmouseenter = () => {
|
||||
this._mouseover = axis;
|
||||
if (this.getEnabled()) {
|
||||
elementKey.classList.add('spinbox-key-hover');
|
||||
elementValue.classList.add('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementValue.onmouseenter = () => {
|
||||
this._mouseover = axis;
|
||||
if (this.getEnabled()) {
|
||||
elementKey.classList.add('spinbox-key-hover');
|
||||
elementValue.classList.add('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementKey.onmouseleave = () => {
|
||||
this._mouseover = null;
|
||||
if (this._dragging !== axis) {
|
||||
elementKey.classList.remove('spinbox-key-hover');
|
||||
elementValue.classList.remove('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementValue.onmouseleave = () => {
|
||||
this._mouseover = null;
|
||||
if (this._dragging !== axis) {
|
||||
elementKey.classList.remove('spinbox-key-hover');
|
||||
elementValue.classList.remove('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
@ -125,9 +106,7 @@ export class VectorSpinboxElement extends ConfigUIElement<Vector3, HTMLDivElemen
|
||||
|
||||
document.addEventListener('mouseup', () => {
|
||||
if (this._dragging !== null) {
|
||||
const elementKey = UIUtil.getElementById(this._getKeyId(this._dragging));
|
||||
const elementValue = UIUtil.getElementById(this._getKeyId(this._dragging));
|
||||
elementKey.classList.remove('spinbox-key-hover');
|
||||
elementValue.classList.remove('spinbox-value-hover');
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import { FileInputElement } from './elements/file_input';
|
||||
import { OutputElement } from './elements/output';
|
||||
import { SliderElement } from './elements/slider';
|
||||
import { ToolbarItemElement } from './elements/toolbar_item';
|
||||
import { VectorSpinboxElement } from './elements/vector_spinbox';
|
||||
|
||||
export interface Group {
|
||||
label: string;
|
||||
@ -48,8 +49,10 @@ export class UI {
|
||||
'input': new FileInputElement()
|
||||
.setFileExtensions(['obj'])
|
||||
.setLabel('Wavefront .obj file'),
|
||||
'rotation': new VectorSpinboxElement()
|
||||
.setLabel('Rotation'),
|
||||
},
|
||||
elementsOrder: ['input'],
|
||||
elementsOrder: ['input', 'rotation'],
|
||||
submitButton: new ButtonElement()
|
||||
.setOnClick(() => {
|
||||
this._appContext.do(EAction.Import);
|
||||
|
||||
@ -75,6 +75,7 @@ export class WorkerClient {
|
||||
importer.parseFile(params.filepath);
|
||||
this._loadedMesh = importer.toMesh();
|
||||
this._loadedMesh.processMesh();
|
||||
this._loadedMesh.rotateMesh(params.rotation.y, params.rotation.x, params.rotation.z);
|
||||
|
||||
return {
|
||||
triangleCount: this._loadedMesh.getTriangleCount(),
|
||||
|
||||
@ -21,20 +21,10 @@ export namespace InitParams {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace SetMaterialsParams {
|
||||
export type Input = {
|
||||
materials: MaterialMap
|
||||
}
|
||||
|
||||
export type Output = {
|
||||
materials: MaterialMap,
|
||||
materialsChanged: string[],
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ImportParams {
|
||||
export type Input = {
|
||||
filepath: string,
|
||||
rotation: Vector3,
|
||||
}
|
||||
|
||||
export type Output = {
|
||||
@ -55,6 +45,17 @@ export namespace RenderMeshParams {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace SetMaterialsParams {
|
||||
export type Input = {
|
||||
materials: MaterialMap
|
||||
}
|
||||
|
||||
export type Output = {
|
||||
materials: MaterialMap,
|
||||
materialsChanged: string[],
|
||||
}
|
||||
}
|
||||
|
||||
export namespace VoxeliseParams {
|
||||
export type Input = {
|
||||
constraintAxis: TAxis,
|
||||
|
||||
17
styles.css
17
styles.css
@ -395,23 +395,20 @@ select:disabled {
|
||||
}
|
||||
|
||||
.spinbox-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: calc(var(--property-height) - 2px);
|
||||
background: var(--prop-standard);
|
||||
border-radius: 5px;
|
||||
flex-grow: 1;
|
||||
height: calc(32px - 8.5px);
|
||||
padding: 8.5px 0px 0px 0px;
|
||||
font-weight: 300;
|
||||
border-width: 1px 1px 1px 0px;
|
||||
border-style: solid;
|
||||
border: rgba(255, 255, 255, 0.0);
|
||||
|
||||
color: var(--text-disabled);
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.0);
|
||||
color: var(--text-standard);
|
||||
}
|
||||
|
||||
.spinbox-value-hover {
|
||||
border: rgba(255, 255, 255, 0.2) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
background: var(--prop-hovered) !important;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { TextureFiltering } from '../src/texture';
|
||||
import { ColourSpace } from '../src/util';
|
||||
import { AppPaths, PathUtil } from '../src/util/path_util';
|
||||
import { Vector3 } from '../src/vector';
|
||||
import { runHeadless, THeadlessConfig } from '../tools/headless';
|
||||
import { TEST_PREAMBLE } from './preamble';
|
||||
|
||||
const baseConfig: THeadlessConfig = {
|
||||
import: {
|
||||
filepath: '', // Must be an absolute path
|
||||
rotation: new Vector3(0, 0, 0),
|
||||
},
|
||||
voxelise: {
|
||||
voxeliser: 'bvh-ray',
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { TextureFiltering } from '../src/texture';
|
||||
import { ColourSpace } from '../src/util';
|
||||
import { AppPaths, PathUtil } from '../src/util/path_util';
|
||||
import { Vector3 } from '../src/vector';
|
||||
import { runHeadless, THeadlessConfig } from '../tools/headless';
|
||||
import { TEST_PREAMBLE } from './preamble';
|
||||
|
||||
const baseConfig: THeadlessConfig = {
|
||||
import: {
|
||||
filepath: '', // Must be an absolute path
|
||||
rotation: new Vector3(0, 0, 0),
|
||||
},
|
||||
voxelise: {
|
||||
voxeliser: 'bvh-ray',
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { TextureFiltering } from '../src/texture';
|
||||
import { ColourSpace } from '../src/util';
|
||||
import { AppPaths, PathUtil } from '../src/util/path_util';
|
||||
import { Vector3 } from '../src/vector';
|
||||
import { runHeadless, THeadlessConfig } from '../tools/headless';
|
||||
import { TEST_PREAMBLE } from './preamble';
|
||||
|
||||
const baseConfig: THeadlessConfig = {
|
||||
import: {
|
||||
filepath: '', // Must be an absolute path
|
||||
rotation: new Vector3(0, 0, 0),
|
||||
},
|
||||
voxelise: {
|
||||
voxeliser: 'bvh-ray',
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { TextureFiltering } from '../src/texture';
|
||||
import { ColourSpace } from '../src/util';
|
||||
import { AppPaths, PathUtil } from '../src/util/path_util';
|
||||
import { Vector3 } from '../src/vector';
|
||||
import { runHeadless, THeadlessConfig } from '../tools/headless';
|
||||
import { TEST_PREAMBLE } from './preamble';
|
||||
|
||||
const baseConfig: THeadlessConfig = {
|
||||
import: {
|
||||
filepath: '', // Must be an absolute path
|
||||
rotation: new Vector3(0, 0, 0),
|
||||
},
|
||||
voxelise: {
|
||||
voxeliser: 'bvh-ray',
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { TextureFiltering } from '../src/texture';
|
||||
import { ColourSpace } from '../src/util';
|
||||
import { Vector3 } from '../src/vector';
|
||||
import { THeadlessConfig } from './headless';
|
||||
|
||||
export const headlessConfig: THeadlessConfig = {
|
||||
import: {
|
||||
filepath: '/Users/lucasdower/ObjToSchematic/res/samples/skull.obj', // Must be an absolute path
|
||||
rotation: new Vector3(0, 0, 0),
|
||||
},
|
||||
voxelise: {
|
||||
constraintAxis: 'y',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user