Fix some more mesher issues

This commit is contained in:
Evert Prants 2024-04-24 20:49:36 +03:00
parent 0a06d7970d
commit 573c3e8f67
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
4 changed files with 69 additions and 28 deletions

View File

@ -17,6 +17,7 @@ export type MsonOperand =
export type MsonVariable = string | number;
export type Mirror3 = [boolean, boolean, boolean];
export type Vec3 = [number, number, number];
export type Vec2 = [number, number];
export type MsonVec3 = Vec3 | [MsonVariable, MsonVariable, MsonVariable];
@ -92,7 +93,7 @@ export interface MsonCompound extends MsonBaseComponent {
* Whether to flip this part's textures.
* @default false
*/
mirror?: boolean | [boolean, boolean, boolean];
mirror?: boolean | Mirror3;
/**
* default type for components (if omitted): mson:box
* allowed types: <mson:box|mson:cone|mson:link|mson:quads|mson:plane|mson:slot>

View File

@ -10,6 +10,7 @@ import {
Vector3,
} from 'three';
import {
Mirror3,
MsonBaseComponent,
MsonBox,
MsonComponent,
@ -28,6 +29,7 @@ import {
} from '../mson';
import { isArrayOfArrays } from '../util/array-of-array';
import { UVMapper } from './uv-mapper';
import { MirrorHelper } from './mirror-helper';
export class ThreeBuilder {
/**
@ -195,6 +197,13 @@ export class ThreeBuilder {
texture?: MsonTexture,
) {
const size = new Vector3().fromArray(component.size as Vec3);
const mirror = (parentComponent as MsonCompound)?.mirror;
const effectiveMirroring: Mirror3 =
mirror !== undefined
? Array.isArray(mirror)
? mirror
: [mirror, mirror, mirror]
: [false, false, false];
const dilate = new Vector3();
if (component.dilate) {
@ -207,8 +216,19 @@ export class ThreeBuilder {
);
const halfSize = size.clone().divideScalar(2);
// Invert Y axis in the offset
offset.setY(offset.y * -1);
const adjustedTranslate = halfSize.clone().add(offset);
// Y axis is reversed in the mesh format.
adjustedTranslate.setY(adjustedTranslate.y - size.y);
// Apply mirrored translations, if applicable
// X axis is reversed as well.
adjustedTranslate.set(
adjustedTranslate.x * (effectiveMirroring[0] ? 1 : -1),
adjustedTranslate.y * (effectiveMirroring[1] ? -1 : 1),
adjustedTranslate.z * (effectiveMirroring[2] ? -1 : 1),
);
const geometry = new BoxGeometry(
size.x + dilate.x,
@ -220,8 +240,8 @@ export class ThreeBuilder {
);
geometry.translate(
-adjustedTranslate.x,
adjustedTranslate.y - size.y,
adjustedTranslate.x,
adjustedTranslate.y,
adjustedTranslate.z,
);
@ -230,12 +250,11 @@ export class ThreeBuilder {
(geometry as any).type = 'BufferGeometry';
delete (geometry as any).parameters;
UVMapper.mapBoxUVs(
size,
geometry,
texture,
(parentComponent as MsonCompound)?.mirror,
);
// Map UVs to box
UVMapper.mapBoxUVs(size, geometry, texture);
// Mirror geometry, if applicable
MirrorHelper.mirrorGeometry(effectiveMirroring, geometry);
const mesh = new Mesh(geometry, this.material);
mesh.name = `${name}__mesh`;

View File

@ -0,0 +1,38 @@
import { BufferGeometry, Matrix4 } from 'three';
import { Mirror3 } from '../mson/mson.type';
/**
* Utilities to mirror a THREE BufferGeometry in set axes.
*/
export class MirrorHelper {
static mirrorGeometry(axes: Mirror3, geometry: BufferGeometry) {
// No axes are mirrored, ignore
if (!axes.some((entry) => !!entry)) return;
// Invert geometry
const inversionMatrix = new Matrix4().makeScale(
axes[0] ? -1 : 1,
axes[1] ? -1 : 1,
axes[2] ? -1 : 1,
);
geometry.applyMatrix4(inversionMatrix);
// Reverse faces winding direction
MirrorHelper.reverseIndexBuffer(geometry);
// Recalculate normals to face correctly
geometry.computeVertexNormals();
}
static reverseIndexBuffer(geometry: BufferGeometry) {
if (!geometry.index) return;
const index = geometry.index.array;
for (let i = 0, il = index.length / 3; i < il; i++) {
let x = index[i * 3];
index[i * 3] = index[i * 3 + 2];
index[i * 3 + 2] = x;
}
geometry.index.needsUpdate = true;
}
}

View File

@ -148,7 +148,6 @@ export class UVMapper {
size: Vector3,
geometry: BoxGeometry,
texture?: MsonTexture,
mirror?: boolean | [boolean, boolean, boolean],
) {
const uvAttribute = geometry.getAttribute('uv') as BufferAttribute;
const index = geometry.getIndex() as BufferAttribute;
@ -161,22 +160,6 @@ export class UVMapper {
let textureOffsetU = texture?.u ?? 0;
let textureOffsetV = texture?.v ?? 0;
const invU: string[] = ['up'];
const invV: string[] = ['up'];
const mirroring =
mirror !== undefined
? Array.isArray(mirror)
? mirror
: [mirror, mirror, mirror]
: [false, false, false];
// TODO: figure out what rest of the components mirror
const [flipX, flipY, flipZ] = mirroring;
if (flipX) {
invU.push('south', 'north');
}
// px nx py ny pz nz
// clockwise count
for (let i = 0; i < index!.count; i += 3) {
@ -195,8 +178,8 @@ export class UVMapper {
textureHeight,
finalU,
finalV,
invU.includes(faceName),
invV.includes(faceName),
faceName === 'up' || faceName === 'down',
faceName === 'up',
);
for (let attrib = 0; attrib < 3; attrib++) {