mpush
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
export let colorMapPreset: PressureColorMapPreset = "emerald";
|
||||
export let matrixDisplayMode: MatrixDisplayMode = "dots";
|
||||
export let stageViewMode: StageViewMode = "webgl";
|
||||
export let modelUrl = "/models/je-skin-model.glb";
|
||||
export let modelUrl = "/models/je-skin-model.gltf";
|
||||
export let replaySectionLabel = "";
|
||||
export let replayPlayLabel = "";
|
||||
export let replayPauseLabel = "";
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
|
||||
const FLOOR_Y = -1.15;
|
||||
const MODEL_FLOOR_CLEARANCE = 0.035;
|
||||
const MODEL_TARGET_HEIGHT = 8.4;
|
||||
const MODEL_TARGET_HEIGHT = 7.4;
|
||||
const MODEL_MIN_SCALE = 0.02;
|
||||
const MODEL_MAX_SCALE = 80;
|
||||
const CAMERA_DISTANCE_FACTOR = 1.35;
|
||||
const CAMERA_DISTANCE_MIN = 7.5;
|
||||
const CAMERA_DISTANCE_MAX = 24;
|
||||
const FIXED_CAMERA_POSITION = new THREE.Vector3(0.8, 3.25, 12.2);
|
||||
const FIXED_CAMERA_TARGET = new THREE.Vector3(0, 2.55, 0);
|
||||
const MODEL_FRONT_ROTATION_Y = -Math.PI / 2;
|
||||
const MODEL_UPRIGHT_ROTATION_Z = Math.PI * 1.5;
|
||||
|
||||
$: copy =
|
||||
locale === "zh-CN"
|
||||
@@ -128,7 +129,41 @@
|
||||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
|
||||
function materialToUnlit(material: THREE.Material): THREE.Material {
|
||||
const source = material as THREE.MeshStandardMaterial & THREE.MeshPhysicalMaterial;
|
||||
const unlit = new THREE.MeshBasicMaterial({
|
||||
color: source.color?.clone() ?? new THREE.Color(0xffffff),
|
||||
map: source.map ?? null,
|
||||
transparent: source.transparent,
|
||||
opacity: source.opacity,
|
||||
alphaMap: source.alphaMap ?? null,
|
||||
side: source.side,
|
||||
depthWrite: source.depthWrite,
|
||||
depthTest: source.depthTest,
|
||||
vertexColors: source.vertexColors,
|
||||
toneMapped: false
|
||||
});
|
||||
|
||||
return unlit;
|
||||
}
|
||||
|
||||
function applyUnlitMaterials(object: THREE.Object3D): void {
|
||||
object.traverse((child) => {
|
||||
const mesh = child as THREE.Mesh;
|
||||
if (!mesh.isMesh || !mesh.material) {
|
||||
return;
|
||||
}
|
||||
|
||||
mesh.castShadow = false;
|
||||
mesh.receiveShadow = false;
|
||||
mesh.material = Array.isArray(mesh.material)
|
||||
? mesh.material.map(materialToUnlit)
|
||||
: materialToUnlit(mesh.material);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeObjectToStage(object: THREE.Object3D): THREE.Box3 {
|
||||
object.rotation.set(0, MODEL_FRONT_ROTATION_Y, MODEL_UPRIGHT_ROTATION_Z);
|
||||
object.updateMatrixWorld(true);
|
||||
let bounds = new THREE.Box3().setFromObject(object);
|
||||
const size = bounds.getSize(new THREE.Vector3());
|
||||
@@ -149,19 +184,14 @@
|
||||
}
|
||||
|
||||
function frameObject(object: THREE.Object3D, camera: THREE.PerspectiveCamera, controls: OrbitControls): void {
|
||||
const bounds = normalizeObjectToStage(object);
|
||||
const size = bounds.getSize(new THREE.Vector3());
|
||||
const maxAxis = Math.max(size.x, size.y, size.z, 1);
|
||||
const distance = clamp(maxAxis * CAMERA_DISTANCE_FACTOR, CAMERA_DISTANCE_MIN, CAMERA_DISTANCE_MAX);
|
||||
const targetY = FLOOR_Y + Math.max(size.y * 0.46, 1.4);
|
||||
|
||||
camera.position.set(distance * 0.48, targetY + distance * 0.24, distance * 0.68);
|
||||
camera.near = Math.max(distance / 80, 0.01);
|
||||
camera.far = distance * 24;
|
||||
normalizeObjectToStage(object);
|
||||
camera.position.copy(FIXED_CAMERA_POSITION);
|
||||
camera.near = 0.05;
|
||||
camera.far = 600;
|
||||
camera.updateProjectionMatrix();
|
||||
controls.target.set(0, targetY, 0);
|
||||
controls.minDistance = Math.max(distance * 0.32, 2);
|
||||
controls.maxDistance = Math.max(distance * 2.5, 12);
|
||||
controls.target.copy(FIXED_CAMERA_TARGET);
|
||||
controls.minDistance = 2.4;
|
||||
controls.maxDistance = 32;
|
||||
controls.update();
|
||||
}
|
||||
|
||||
@@ -186,14 +216,15 @@
|
||||
scene.fog = new THREE.FogExp2(0x03070d, 0.028);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(38, 1, 0.05, 600);
|
||||
camera.position.set(8, 6, 9);
|
||||
camera.position.copy(FIXED_CAMERA_POSITION);
|
||||
camera.lookAt(FIXED_CAMERA_TARGET);
|
||||
|
||||
const controls = new OrbitControls(camera, canvasEl);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.08;
|
||||
controls.minDistance = 2.4;
|
||||
controls.maxDistance = 32;
|
||||
controls.target.set(0, FLOOR_Y + 3.2, 0);
|
||||
controls.target.copy(FIXED_CAMERA_TARGET);
|
||||
|
||||
const labGroup = new THREE.Group();
|
||||
scene.add(labGroup);
|
||||
@@ -241,16 +272,8 @@
|
||||
floor.position.y = FLOOR_Y - 0.018;
|
||||
labGroup.add(floor);
|
||||
|
||||
const ambient = new THREE.AmbientLight(0x9fb8d0, 0.22);
|
||||
const keyLight = new THREE.DirectionalLight(0x7be7ff, 1.5);
|
||||
keyLight.position.set(8, 12, 8);
|
||||
const rimLight = new THREE.PointLight(0xa6ff7a, 26, 24, 2.1);
|
||||
rimLight.position.set(-4.5, 4.8, -3.6);
|
||||
const sideLight = new THREE.PointLight(0x5c8cff, 15, 28, 1.7);
|
||||
sideLight.position.set(5.8, 3.2, -5.4);
|
||||
scene.add(ambient, keyLight, rimLight, sideLight);
|
||||
|
||||
let activeModel: THREE.Object3D = buildPlaceholderModel();
|
||||
applyUnlitMaterials(activeModel);
|
||||
scene.add(activeModel);
|
||||
frameObject(activeModel, camera, controls);
|
||||
|
||||
@@ -261,13 +284,7 @@
|
||||
scene.remove(activeModel);
|
||||
disposeObject3D(activeModel);
|
||||
activeModel = gltf.scene;
|
||||
activeModel.traverse((child) => {
|
||||
const mesh = child as THREE.Mesh;
|
||||
if (mesh.isMesh) {
|
||||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
applyUnlitMaterials(activeModel);
|
||||
scene.add(activeModel);
|
||||
frameObject(activeModel, camera, controls);
|
||||
loadState = "ready";
|
||||
|
||||
Reference in New Issue
Block a user