abysmal hacking for nominal results
This commit is contained in:
parent
3be6493f3d
commit
b959cea254
@ -100,6 +100,14 @@ export interface MsonCompound extends MsonBaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type MsonFace = 'up' | 'down' | 'east' | 'west' | 'south' | 'north';
|
export type MsonFace = 'up' | 'down' | 'east' | 'west' | 'south' | 'north';
|
||||||
|
export const MsonFaces: MsonFace[] = [
|
||||||
|
'up',
|
||||||
|
'down',
|
||||||
|
'east',
|
||||||
|
'west',
|
||||||
|
'south',
|
||||||
|
'north',
|
||||||
|
];
|
||||||
|
|
||||||
export type MsonPlanarXYZWH = [
|
export type MsonPlanarXYZWH = [
|
||||||
MsonVariable,
|
MsonVariable,
|
||||||
|
@ -2,19 +2,19 @@ import { resolve } from 'path';
|
|||||||
import { ModelStore, MsonEvaluate } from '.';
|
import { ModelStore, MsonEvaluate } from '.';
|
||||||
import { fillStoreFromFilesystem, saveGeometry } from './util/node';
|
import { fillStoreFromFilesystem, saveGeometry } from './util/node';
|
||||||
import { ThreeBuilder } from './three';
|
import { ThreeBuilder } from './three';
|
||||||
import { MeshBasicMaterial } from 'three';
|
import { MeshBasicMaterial, MeshLambertMaterial } from 'three';
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const store = new ModelStore();
|
const store = new ModelStore();
|
||||||
const evaluate = new MsonEvaluate(store);
|
const evaluate = new MsonEvaluate(store);
|
||||||
const mat = new MeshBasicMaterial();
|
const mat = new MeshLambertMaterial();
|
||||||
const builder = new ThreeBuilder(mat);
|
const builder = new ThreeBuilder(mat);
|
||||||
|
|
||||||
await fillStoreFromFilesystem(store, resolve(process.cwd(), 'inputs'));
|
await fillStoreFromFilesystem(store, resolve(process.cwd(), 'inputs'));
|
||||||
|
|
||||||
// mson:steve
|
// mson:steve
|
||||||
// minelittlepony:steve_pony
|
// minelittlepony:steve_pony
|
||||||
const final = evaluate.evaluateModel('mson:biped');
|
const final = evaluate.evaluateModel('minelittlepony:races/steve/alicorn');
|
||||||
// console.log(final.texture);
|
// console.log(final.texture);
|
||||||
console.dir(final._dataEvaluated, {
|
console.dir(final._dataEvaluated, {
|
||||||
depth: 20,
|
depth: 20,
|
||||||
|
@ -5,6 +5,8 @@ import {
|
|||||||
MathUtils,
|
MathUtils,
|
||||||
Mesh,
|
Mesh,
|
||||||
Object3D,
|
Object3D,
|
||||||
|
PlaneGeometry,
|
||||||
|
Vector2,
|
||||||
Vector3,
|
Vector3,
|
||||||
} from 'three';
|
} from 'three';
|
||||||
import {
|
import {
|
||||||
@ -14,11 +16,53 @@ import {
|
|||||||
MsonComponentType,
|
MsonComponentType,
|
||||||
MsonCompound,
|
MsonCompound,
|
||||||
MsonCompoundComponent,
|
MsonCompoundComponent,
|
||||||
|
MsonData,
|
||||||
MsonEvaluatedModel,
|
MsonEvaluatedModel,
|
||||||
|
MsonFace,
|
||||||
|
MsonFaces,
|
||||||
|
MsonPlanar,
|
||||||
|
MsonPlanarPlane,
|
||||||
|
MsonPlanarXYZWHUVXY,
|
||||||
|
MsonPlane,
|
||||||
|
MsonSlot,
|
||||||
Vec3,
|
Vec3,
|
||||||
} from '../mson';
|
} from '../mson';
|
||||||
|
import { isArrayOfArrays } from '../util/array-of-array';
|
||||||
|
|
||||||
export class ThreeBuilder {
|
export class ThreeBuilder {
|
||||||
|
static normals: Record<MsonFace, Vector3> = {
|
||||||
|
up: new Vector3(0, -1, 0),
|
||||||
|
down: new Vector3(0, 1, 0),
|
||||||
|
east: new Vector3(1, 0, 0),
|
||||||
|
west: new Vector3(-1, 0, 0),
|
||||||
|
south: new Vector3(0, 0, 1),
|
||||||
|
north: new Vector3(0, 0, -1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static pocConvert: Record<
|
||||||
|
MsonFace,
|
||||||
|
(pos: Vector3, size: Vector2) => Vector3
|
||||||
|
> = {
|
||||||
|
up: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x + size.x / 2, pos.y, pos.z + size.y / 2);
|
||||||
|
},
|
||||||
|
down: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x + size.x / 2, pos.y, pos.z + size.y / 2);
|
||||||
|
},
|
||||||
|
east: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x, pos.y + size.y / 2, pos.z + size.x / 2);
|
||||||
|
},
|
||||||
|
west: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x, pos.y + size.y / 2, pos.z + size.x / 2);
|
||||||
|
},
|
||||||
|
south: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x + size.x / 2, pos.y + size.y / 2, pos.z);
|
||||||
|
},
|
||||||
|
north: function (pos: Vector3, size: Vector2): Vector3 {
|
||||||
|
return new Vector3(pos.x + size.x / 2, pos.y + size.y / 2, pos.z);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
constructor(private readonly material: Material) {}
|
constructor(private readonly material: Material) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,15 +99,56 @@ export class ThreeBuilder {
|
|||||||
parent: Object3D,
|
parent: Object3D,
|
||||||
parentComponent?: MsonComponent,
|
parentComponent?: MsonComponent,
|
||||||
) {
|
) {
|
||||||
|
const wrapper = this.createWrapper(
|
||||||
|
name,
|
||||||
|
component.type || 'mson:compound',
|
||||||
|
component,
|
||||||
|
);
|
||||||
|
parent.add(wrapper);
|
||||||
|
|
||||||
// Compound objects
|
// Compound objects
|
||||||
if (!component.type || component.type === 'mson:compound') {
|
if (!component.type || component.type === 'mson:compound') {
|
||||||
return this.makeMsonCompound(
|
this.makeMsonCompound(
|
||||||
name,
|
name,
|
||||||
component as MsonCompound,
|
component as MsonCompound,
|
||||||
parent,
|
wrapper,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (component.type === 'mson:slot') {
|
||||||
|
for (const [childName, child] of Object.entries(component.data)) {
|
||||||
|
this.makeGeometry(childName, child, wrapper, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.type === 'mson:planar') {
|
||||||
|
this.makeMsonPlanar(name, component, wrapper, parentComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.type === 'mson:plane') {
|
||||||
|
this.makeMsonPlane(name, component, wrapper, parentComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
(component as MsonCompound).cubes?.forEach(
|
||||||
|
(part: MsonCompoundComponent) => {
|
||||||
|
if (!part.type || part.type === 'mson:box') {
|
||||||
|
this.makeMsonBox(name, part as MsonBox, wrapper, component);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.type === 'mson:plane') {
|
||||||
|
this.makeMsonPlane(name, part as MsonPlane, wrapper, component);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (component.children) {
|
||||||
|
for (const [childName, child] of Object.entries(component.children)) {
|
||||||
|
this.makeGeometry(childName, child, wrapper, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected makeMsonCompound(
|
protected makeMsonCompound(
|
||||||
@ -71,17 +156,7 @@ export class ThreeBuilder {
|
|||||||
component: MsonCompound,
|
component: MsonCompound,
|
||||||
parent: Object3D,
|
parent: Object3D,
|
||||||
parentComponent?: MsonComponent,
|
parentComponent?: MsonComponent,
|
||||||
) {
|
) {}
|
||||||
const wrapper = this.createWrapper(name, component);
|
|
||||||
parent.add(wrapper);
|
|
||||||
|
|
||||||
component.cubes?.forEach((part: MsonCompoundComponent) => {
|
|
||||||
if (!part.type || part.type === 'mson:box') {
|
|
||||||
this.makeMsonBox(name, part as MsonBox, wrapper, component);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected makeMsonBox(
|
protected makeMsonBox(
|
||||||
name: string,
|
name: string,
|
||||||
@ -97,23 +172,7 @@ export class ThreeBuilder {
|
|||||||
else dilate.set(component.dilate, component.dilate, component.dilate);
|
else dilate.set(component.dilate, component.dilate, component.dilate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rotate = new Vector3();
|
|
||||||
if (parentComponent?.rotate) {
|
|
||||||
rotate.fromArray(
|
|
||||||
(parentComponent.rotate as Vec3).map((entry) =>
|
|
||||||
MathUtils.degToRad(entry),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pos = new Vector3();
|
|
||||||
if (parentComponent?.pivot) {
|
|
||||||
pos.fromArray(parentComponent.pivot as Vec3);
|
|
||||||
}
|
|
||||||
pos.setY(pos.y * -1);
|
|
||||||
|
|
||||||
const offset = new Vector3().fromArray(component.from as Vec3);
|
const offset = new Vector3().fromArray(component.from as Vec3);
|
||||||
const halfOffset = offset.clone().divideScalar(2);
|
|
||||||
const halfSize = size.clone().divideScalar(2);
|
const halfSize = size.clone().divideScalar(2);
|
||||||
|
|
||||||
offset.setY(offset.y * -1);
|
offset.setY(offset.y * -1);
|
||||||
@ -133,30 +192,157 @@ export class ThreeBuilder {
|
|||||||
adjustedTranslate.y - size.y,
|
adjustedTranslate.y - size.y,
|
||||||
adjustedTranslate.z,
|
adjustedTranslate.z,
|
||||||
);
|
);
|
||||||
geometry.rotateX(rotate.x);
|
|
||||||
geometry.rotateY(rotate.y);
|
|
||||||
geometry.rotateZ(rotate.z);
|
|
||||||
|
|
||||||
// FIXME: hack toJSON
|
// FIXME: hack toJSON
|
||||||
(geometry as any).type = 'BufferGeometry';
|
(geometry as any).type = 'BufferGeometry';
|
||||||
delete (geometry as any).parameters;
|
delete (geometry as any).parameters;
|
||||||
|
|
||||||
// TODO: apply UVs
|
// TODO: apply UVs
|
||||||
// pos.add(halfOffset).add(halfSize);
|
|
||||||
|
|
||||||
const mesh = new Mesh(geometry, this.material);
|
const mesh = new Mesh(geometry, this.material);
|
||||||
mesh.name = `${name}__mesh`;
|
mesh.name = `${name}__mesh`;
|
||||||
mesh.position.copy(pos);
|
|
||||||
mesh.updateMatrix();
|
mesh.updateMatrix();
|
||||||
|
|
||||||
parent.add(mesh);
|
parent.add(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createWrapper(name: string, component: MsonBaseComponent) {
|
protected makeMsonPlaneFace(
|
||||||
|
face: MsonFace,
|
||||||
|
parent: Object3D,
|
||||||
|
pos: Vector3,
|
||||||
|
size: Vector2,
|
||||||
|
uv: Vector2,
|
||||||
|
mirror?: boolean | [boolean, boolean],
|
||||||
|
invertY = false,
|
||||||
|
) {
|
||||||
|
const planeGeom = new PlaneGeometry(size.x, size.y);
|
||||||
|
let axisNormal = ThreeBuilder.normals[face];
|
||||||
|
if (invertY) {
|
||||||
|
axisNormal = axisNormal.clone().setY(axisNormal.y * -1);
|
||||||
|
pos.setY(pos.y * -1);
|
||||||
|
if (['east', 'west', 'south', 'north'].includes(face))
|
||||||
|
size.setY(size.y * -1);
|
||||||
|
}
|
||||||
|
const adjustedTranslate = ThreeBuilder.pocConvert[face](pos, size);
|
||||||
|
planeGeom.lookAt(axisNormal);
|
||||||
|
planeGeom.translate(
|
||||||
|
adjustedTranslate.x,
|
||||||
|
adjustedTranslate.y,
|
||||||
|
adjustedTranslate.z,
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: apply UVs
|
||||||
|
|
||||||
|
// FIXME: hack toJSON
|
||||||
|
(planeGeom as any).type = 'BufferGeometry';
|
||||||
|
delete (planeGeom as any).parameters;
|
||||||
|
|
||||||
|
const mesh = new Mesh(planeGeom, this.material);
|
||||||
|
// mesh.position.copy(pos);
|
||||||
|
mesh.name = face;
|
||||||
|
parent.add(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected makeMsonPlanar(
|
||||||
|
name: string,
|
||||||
|
component: MsonPlanar,
|
||||||
|
parent: Object3D,
|
||||||
|
parentComponent?: MsonComponent,
|
||||||
|
) {
|
||||||
|
const wrapper = new Object3D();
|
||||||
|
wrapper.name = name;
|
||||||
|
wrapper.userData.type = component.type;
|
||||||
|
parent.add(wrapper);
|
||||||
|
|
||||||
|
for (const face of MsonFaces) {
|
||||||
|
if (!component[face]) continue;
|
||||||
|
const toMake = (
|
||||||
|
isArrayOfArrays(component[face]) ? component[face] : [component[face]]
|
||||||
|
) as MsonPlanarXYZWHUVXY[];
|
||||||
|
for (const faceinfo of toMake) {
|
||||||
|
const planePos = new Vector3();
|
||||||
|
const size = new Vector2();
|
||||||
|
const uv = new Vector2();
|
||||||
|
let mirror: [boolean, boolean] = [false, false];
|
||||||
|
|
||||||
|
planePos.fromArray(faceinfo as number[]);
|
||||||
|
// planePos.setY(planePos.y * -1);
|
||||||
|
size.fromArray(faceinfo as number[], 3);
|
||||||
|
|
||||||
|
if (faceinfo.length > 5) {
|
||||||
|
uv.fromArray(faceinfo as number[], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (faceinfo.length > 7) {
|
||||||
|
mirror = [faceinfo[7] as boolean, faceinfo[8] as boolean];
|
||||||
|
}
|
||||||
|
this.makeMsonPlaneFace(face, wrapper, planePos, size, uv, mirror, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper.updateMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected makeMsonPlane(
|
||||||
|
name: string,
|
||||||
|
component: MsonPlane,
|
||||||
|
parent: Object3D,
|
||||||
|
parentComponent?: MsonComponent,
|
||||||
|
) {
|
||||||
|
const wrapper = new Object3D();
|
||||||
|
wrapper.name = name;
|
||||||
|
wrapper.userData.type = component.type;
|
||||||
|
parent.add(wrapper);
|
||||||
|
|
||||||
|
const planePos = new Vector3();
|
||||||
|
const size = new Vector2();
|
||||||
|
const uv = new Vector2();
|
||||||
|
|
||||||
|
let mirror: [boolean, boolean] = [false, false];
|
||||||
|
|
||||||
|
if (component.position) planePos.fromArray(component.position as number[]);
|
||||||
|
if (component.size) size.fromArray(component.size as number[]);
|
||||||
|
|
||||||
|
uv.set(component.texture?.u ?? 0, component.texture?.v ?? 0);
|
||||||
|
|
||||||
|
if (component.mirror) mirror = component.mirror;
|
||||||
|
this.makeMsonPlaneFace(
|
||||||
|
component.face as MsonFace,
|
||||||
|
wrapper,
|
||||||
|
planePos,
|
||||||
|
size,
|
||||||
|
uv,
|
||||||
|
mirror,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createWrapper(
|
||||||
|
name: string,
|
||||||
|
typeName: string,
|
||||||
|
component: MsonBaseComponent,
|
||||||
|
) {
|
||||||
let wrapper = new Object3D();
|
let wrapper = new Object3D();
|
||||||
wrapper.name = name;
|
wrapper.name = name;
|
||||||
wrapper.userData.type = 'mson:compound';
|
wrapper.userData.type = typeName;
|
||||||
wrapper.visible = component.visible ?? true;
|
wrapper.visible = component.visible ?? true;
|
||||||
|
|
||||||
|
const rotate = new Vector3();
|
||||||
|
if (component?.rotate) {
|
||||||
|
rotate.fromArray(
|
||||||
|
(component.rotate as Vec3).map((entry, index) =>
|
||||||
|
MathUtils.degToRad(index !== 1 ? entry * -1 : entry),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
wrapper.rotation.setFromVector3(rotate, 'XYZ');
|
||||||
|
|
||||||
|
const pos = new Vector3();
|
||||||
|
if (component?.pivot) {
|
||||||
|
pos.fromArray(component.pivot as Vec3);
|
||||||
|
}
|
||||||
|
pos.setY(pos.y * -1);
|
||||||
|
wrapper.position.copy(pos);
|
||||||
|
wrapper.updateMatrix();
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
src/util/array-of-array.ts
Normal file
2
src/util/array-of-array.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const isArrayOfArrays = (input: any) =>
|
||||||
|
Array.isArray(input) && input.every((item) => Array.isArray(item));
|
Loading…
Reference in New Issue
Block a user