663 lines
23 KiB
JavaScript
663 lines
23 KiB
JavaScript
import * as THREE from 'three';
|
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
|
|
|
|
let apiURL = '';
|
|
let currentDepthStrength = 1.5;
|
|
let currentDofStrength = 0.0;
|
|
let currentFocusDistance = 0.0;
|
|
let currentZOffset = 0.0; // 添加Z轴偏移变量
|
|
let currentDepthMesh = null;
|
|
const BASE_CAMERA_DISTANCE = 5.0; // 修改基础相机距离为5(fov90时)
|
|
let currentScreenshotSize = 1024; // 默认截图尺寸
|
|
|
|
// 添加Quilts相关变量
|
|
let currentQuiltsNum = 4;
|
|
let currentQuiltsAngleRange = 14; // 默认角度差为14度
|
|
let isQuiltsMode = false;
|
|
let quiltsProgress = 0;
|
|
let quiltsStartTime = null;
|
|
let quiltsCurrentFrame = 0;
|
|
let quiltsTargetRotation = 0;
|
|
let quiltsIsRotating = false;
|
|
const QUILTS_DURATION = 1000; // 1秒完成一次旋转
|
|
|
|
// 添加存储截图的数组
|
|
let quiltsScreenshots = [];
|
|
|
|
// Listen for messages from the parent window
|
|
window.addEventListener('message', function(event) {
|
|
if (event.data.type === 'init') {
|
|
apiURL = event.data.apiURL;
|
|
} else if (event.data.type === 'update') {
|
|
if (event.data.depthStrength !== undefined) {
|
|
currentDepthStrength = event.data.depthStrength;
|
|
if (currentDepthMesh && currentDepthMesh.material) {
|
|
currentDepthMesh.material.uniforms.depthScale.value = 5.0 * currentDepthStrength;
|
|
// 当深度强度改变时,也需要更新Z轴偏移
|
|
const finalZOffset = currentZOffset - (currentDepthStrength * 5 / 2);
|
|
currentDepthMesh.position.z = finalZOffset;
|
|
}
|
|
}
|
|
if (event.data.dofStrength !== undefined) {
|
|
currentDofStrength = event.data.dofStrength;
|
|
if (currentDepthMesh && currentDepthMesh.material) {
|
|
currentDepthMesh.material.uniforms.dofStrength.value = currentDofStrength;
|
|
}
|
|
}
|
|
if (event.data.focusDistance !== undefined) {
|
|
currentFocusDistance = event.data.focusDistance;
|
|
if (currentDepthMesh && currentDepthMesh.material) {
|
|
currentDepthMesh.material.uniforms.focusDistance.value = currentFocusDistance;
|
|
}
|
|
}
|
|
if (event.data.referenceImage && event.data.depthMap) {
|
|
main(event.data.referenceImage, event.data.depthMap);
|
|
}
|
|
} else if (event.data.type === 'resetView') {
|
|
resetView(event.data.depthStrength);
|
|
} else if (event.data.type === 'updateQuiltsNum') {
|
|
currentQuiltsNum = event.data.value;
|
|
} else if (event.data.type === 'updateQuiltsAngleRange') {
|
|
currentQuiltsAngleRange = event.data.value;
|
|
} else if (event.data.type === 'updateScreenshotSize') {
|
|
currentScreenshotSize = event.data.value;
|
|
} else if (event.data.type === 'toggleQuilts') {
|
|
if (!isQuiltsMode) {
|
|
startQuilts();
|
|
} else {
|
|
stopQuilts();
|
|
}
|
|
} else if (event.data.type === 'updateZOffset') {
|
|
currentZOffset = event.data.value;
|
|
if (currentDepthMesh) {
|
|
// 计算最终的Z轴偏移值
|
|
const finalZOffset = currentZOffset - (currentDepthStrength * 5 / 2);
|
|
currentDepthMesh.position.z = finalZOffset;
|
|
}
|
|
} else if (event.data.type === 'updateCameraFOV') {
|
|
// 更新相机FOV
|
|
camera.fov = event.data.value;
|
|
camera.updateProjectionMatrix();
|
|
}
|
|
}, false);
|
|
|
|
const visualizer = document.getElementById("visualizer");
|
|
const container = document.getElementById("container");
|
|
const progressDialog = document.getElementById("progress-dialog");
|
|
const progressIndicator = document.getElementById("progress-indicator");
|
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true, extensions: {
|
|
derivatives: true
|
|
}});
|
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
|
|
// 添加旋转信息显示元素
|
|
const rotationDisplay = document.createElement('div');
|
|
rotationDisplay.style.cssText = `
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
color: white;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-family: monospace;
|
|
font-size: 10px;
|
|
z-index: 1000;
|
|
margin-bottom: 2px;
|
|
width: 195px;
|
|
text-align: left;
|
|
white-space: nowrap;
|
|
line-height: 1.2;
|
|
`;
|
|
container.appendChild(rotationDisplay);
|
|
|
|
// 修改距离显示元素
|
|
const distanceDisplay = document.createElement('div');
|
|
distanceDisplay.style.cssText = `
|
|
position: absolute;
|
|
top: 32px;
|
|
left: 10px;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
color: white;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-family: monospace;
|
|
font-size: 10px;
|
|
z-index: 1000;
|
|
width: 85px;
|
|
text-align: left;
|
|
line-height: 1.2;
|
|
`;
|
|
container.appendChild(distanceDisplay);
|
|
|
|
// 设置1:1画布
|
|
function updateRendererSize() {
|
|
const size = Math.min(window.innerWidth, window.innerHeight);
|
|
renderer.setSize(size, size);
|
|
camera.aspect = 1;
|
|
camera.updateProjectionMatrix();
|
|
|
|
// 将渲染器容器移到左侧
|
|
container.style.cssText = `
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: ${size}px;
|
|
height: ${size}px;
|
|
`;
|
|
}
|
|
|
|
const pmremGenerator = new THREE.PMREMGenerator(renderer);
|
|
|
|
// scene
|
|
const scene = new THREE.Scene();
|
|
scene.background = new THREE.Color(0x000000);
|
|
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(renderer), 0.04).texture;
|
|
|
|
// 添加中心点标记
|
|
const centerPoint = new THREE.Mesh(
|
|
new THREE.SphereGeometry(0.1, 16, 16),
|
|
new THREE.MeshBasicMaterial({ color: 0xff0000 })
|
|
);
|
|
centerPoint.name = 'centerPoint';
|
|
scene.add(centerPoint);
|
|
|
|
// 添加坐标轴
|
|
const axesHelper = new THREE.AxesHelper(5);
|
|
axesHelper.name = 'axesHelper';
|
|
scene.add(axesHelper);
|
|
|
|
const ambientLight = new THREE.AmbientLight(0xffffff);
|
|
|
|
const camera = new THREE.PerspectiveCamera(7, 1, 0.1, 1000); // 设置默认FOV为7度
|
|
camera.position.set(0, 0, 10);
|
|
const pointLight = new THREE.PointLight(0xffffff, 15);
|
|
camera.add(pointLight);
|
|
|
|
const controls = new OrbitControls(camera, renderer.domElement);
|
|
controls.target.set(0, 0, 0);
|
|
controls.update();
|
|
controls.enablePan = true;
|
|
controls.enableDamping = true;
|
|
controls.rotateSpeed = 1.0; // 调整旋转速度
|
|
controls.dampingFactor = 0.05; // 调整阻尼系数
|
|
|
|
// 修改距离显示函数
|
|
function updateDistanceDisplay() {
|
|
const distance = camera.position.length();
|
|
distanceDisplay.textContent = `Distance: ${distance.toFixed(1)}`;
|
|
}
|
|
|
|
// 修改OrbitControls的更新回调
|
|
controls.addEventListener('change', () => {
|
|
updateDistanceDisplay();
|
|
updateRotationDisplay();
|
|
});
|
|
|
|
// 修改窗口大小处理函数
|
|
window.onresize = function () {
|
|
updateRendererSize();
|
|
};
|
|
|
|
updateRendererSize();
|
|
container.appendChild(renderer.domElement);
|
|
|
|
var lastReferenceImage = "";
|
|
var lastDepthMap = "";
|
|
var needUpdate = false;
|
|
|
|
function frameUpdate() {
|
|
var referenceImage = visualizer.getAttribute("reference_image");
|
|
var depthMap = visualizer.getAttribute("depth_map");
|
|
if (referenceImage == lastReferenceImage && depthMap == lastDepthMap) {
|
|
if (needUpdate) {
|
|
if (isQuiltsMode) {
|
|
updateQuilts();
|
|
} else {
|
|
controls.update();
|
|
}
|
|
renderer.render(scene, camera);
|
|
updateDistanceDisplay();
|
|
updateRotationDisplay();
|
|
}
|
|
requestAnimationFrame(frameUpdate);
|
|
} else {
|
|
needUpdate = false;
|
|
scene.clear();
|
|
progressDialog.open = true;
|
|
lastReferenceImage = referenceImage;
|
|
lastDepthMap = depthMap;
|
|
main(JSON.parse(lastReferenceImage), JSON.parse(lastDepthMap));
|
|
}
|
|
}
|
|
|
|
const onProgress = function (xhr) {
|
|
if (xhr.lengthComputable) {
|
|
progressIndicator.value = xhr.loaded / xhr.total * 100;
|
|
}
|
|
};
|
|
|
|
const onError = function (e) {
|
|
console.error(e);
|
|
};
|
|
|
|
// 修改自适应回正函数
|
|
function resetView(depthStrength) {
|
|
const maxDisplacement = 2.5 * depthStrength;
|
|
|
|
// 计算基于FOV的相机回正距离补偿
|
|
const fovRadians = THREE.MathUtils.degToRad(camera.fov);
|
|
const fovCompensation = 1 / Math.tan(fovRadians / 2);
|
|
|
|
// 基础距离 * FOV补偿系数
|
|
const cameraDistance = (BASE_CAMERA_DISTANCE* fovCompensation) + (maxDisplacement * 0.5) + currentZOffset ;
|
|
|
|
// 重置相机位置和旋转
|
|
camera.position.set(0, 0, cameraDistance);
|
|
camera.rotation.set(0, 0, 0);
|
|
controls.target.set(0, 0, 0);
|
|
controls.update();
|
|
updateDistanceDisplay();
|
|
updateRotationDisplay();
|
|
}
|
|
|
|
async function main(referenceImageParams, depthMapParams) {
|
|
let referenceTexture, depthTexture;
|
|
let imageWidth = 10;
|
|
let imageHeight = 10;
|
|
|
|
// 清除现有场景内容
|
|
scene.clear();
|
|
|
|
// 重新添加基础场景元素
|
|
scene.background = new THREE.Color(0x000000);
|
|
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(renderer), 0.04).texture;
|
|
|
|
// 添加中心点标记
|
|
const centerPoint = new THREE.Mesh(
|
|
new THREE.SphereGeometry(0.1, 16, 16),
|
|
new THREE.MeshBasicMaterial({ color: 0xff0000 })
|
|
);
|
|
centerPoint.name = 'centerPoint';
|
|
scene.add(centerPoint);
|
|
|
|
// 添加坐标轴
|
|
const axesHelper = new THREE.AxesHelper(5);
|
|
axesHelper.name = 'axesHelper';
|
|
scene.add(axesHelper);
|
|
|
|
// 添加环境光和相机
|
|
scene.add(ambientLight);
|
|
scene.add(camera);
|
|
|
|
if (referenceImageParams?.filename) {
|
|
const referenceImageUrl = `${apiURL}/view?` + new URLSearchParams(referenceImageParams).toString();
|
|
const referenceImageExt = referenceImageParams.filename.slice(referenceImageParams.filename.lastIndexOf(".") + 1);
|
|
|
|
if (referenceImageExt === "png" || referenceImageExt === "jpg" || referenceImageExt === "jpeg") {
|
|
const referenceImageLoader = new THREE.TextureLoader();
|
|
referenceTexture = await new Promise((resolve, reject) => {
|
|
referenceImageLoader.load(referenceImageUrl, (texture) => {
|
|
imageWidth = 10;
|
|
imageHeight = texture.image.height / (texture.image.width / 10);
|
|
resolve(texture);
|
|
}, undefined, reject);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (depthMapParams?.filename) {
|
|
const depthMapUrl = `${apiURL}/view?` + new URLSearchParams(depthMapParams).toString();
|
|
const depthMapExt = depthMapParams.filename.slice(depthMapParams.filename.lastIndexOf(".") + 1);
|
|
|
|
if (depthMapExt === "png" || depthMapExt === "jpg" || depthMapExt === "jpeg") {
|
|
const depthMapLoader = new THREE.TextureLoader();
|
|
depthTexture = await depthMapLoader.loadAsync(depthMapUrl);
|
|
}
|
|
}
|
|
|
|
if (referenceTexture && depthTexture) {
|
|
if (currentDepthMesh) {
|
|
scene.remove(currentDepthMesh);
|
|
currentDepthMesh.geometry.dispose();
|
|
currentDepthMesh.material.dispose();
|
|
}
|
|
|
|
const depthMaterial = new THREE.ShaderMaterial({
|
|
uniforms: {
|
|
referenceTexture: { value: referenceTexture },
|
|
depthTexture: { value: depthTexture },
|
|
depthScale: { value: 5.0 * currentDepthStrength },
|
|
dofStrength: { value: currentDofStrength },
|
|
focusDistance: { value: currentFocusDistance },
|
|
ambientLightColor: { value: new THREE.Color(0.2, 0.2, 0.2) },
|
|
lightPosition: { value: new THREE.Vector3(2, 2, 2) },
|
|
lightColor: { value: new THREE.Color(1, 1, 1) },
|
|
lightIntensity: { value: 1.0 },
|
|
shininess: { value: 30 },
|
|
},
|
|
vertexShader: `
|
|
uniform sampler2D depthTexture;
|
|
uniform float depthScale;
|
|
|
|
varying vec2 vUv;
|
|
varying float vDepth;
|
|
varying vec3 vNormal;
|
|
varying vec3 vViewPosition;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
|
|
float depth = texture2D(depthTexture, uv).r;
|
|
vec3 displacement = normal * depth * depthScale;
|
|
vec3 displacedPosition = position + displacement;
|
|
|
|
vec4 worldPosition = modelMatrix * vec4(displacedPosition, 1.0);
|
|
vNormal = normalize(normalMatrix * normal);
|
|
vViewPosition = (viewMatrix * worldPosition).xyz;
|
|
|
|
gl_Position = projectionMatrix * viewMatrix * worldPosition;
|
|
|
|
vDepth = depth;
|
|
}
|
|
`,
|
|
fragmentShader: `
|
|
uniform sampler2D referenceTexture;
|
|
uniform float dofStrength;
|
|
uniform float focusDistance;
|
|
|
|
varying vec2 vUv;
|
|
varying float vDepth;
|
|
varying vec3 vViewPosition;
|
|
|
|
// 优化的高斯模糊采样函数
|
|
vec4 gaussianBlur(sampler2D tex, vec2 uv, float blurFactor) {
|
|
vec4 color = vec4(0.0);
|
|
float total = 0.0;
|
|
|
|
// 使用高斯函数计算权重
|
|
float sigma = 4.0; // 控制高斯分布的宽度
|
|
float weights[8];
|
|
float offsets[8];
|
|
|
|
// 计算权重和偏移
|
|
for(int i = 0; i < 8; i++) {
|
|
offsets[i] = float(i);
|
|
// 高斯函数: exp(-(x^2)/(2*sigma^2))
|
|
weights[i] =0.005 + exp(-(float(i) * float(i)) / (2.0 * sigma * sigma));
|
|
}
|
|
|
|
// 水平方向
|
|
for(int i = 0; i < 8; i++) {
|
|
float offset = offsets[i] * blurFactor * 0.005;
|
|
color += texture2D(tex, uv + vec2(offset, 0.0)) * weights[i];
|
|
color += texture2D(tex, uv - vec2(offset, 0.0)) * weights[i];
|
|
total += weights[i] * 2.0;
|
|
}
|
|
|
|
// 垂直方向
|
|
vec4 color2 = vec4(0.0);
|
|
for(int i = 0; i < 8; i++) {
|
|
float offset = offsets[i] * blurFactor * 0.005;
|
|
color2 += texture2D(tex, uv + vec2(0.0, offset)) * weights[i];
|
|
color2 += texture2D(tex, uv - vec2(0.0, offset)) * weights[i];
|
|
total += weights[i] * 2.0;
|
|
}
|
|
|
|
return (color + color2) / total;
|
|
}
|
|
|
|
void main() {
|
|
vec4 referenceColor = texture2D(referenceTexture, vUv);
|
|
|
|
// 计算景深模糊
|
|
float depthDiff = abs(vDepth - focusDistance);
|
|
float blurFactor = pow(depthDiff, (0.25 - (0.05 * dofStrength)) ) * dofStrength;
|
|
|
|
// 应用优化后的高斯模糊
|
|
vec4 blurredColor = gaussianBlur(referenceTexture, vUv, blurFactor);
|
|
|
|
// 调整亮度
|
|
blurredColor.rgb *= 0.99; // 略微降低亮度
|
|
|
|
// 混合原始颜色和模糊颜色
|
|
gl_FragColor = mix(referenceColor, blurredColor, blurFactor);
|
|
}
|
|
`
|
|
});
|
|
|
|
const planeGeometry = new THREE.PlaneGeometry(imageWidth, imageHeight, 360, 360);
|
|
currentDepthMesh = new THREE.Mesh(planeGeometry, depthMaterial);
|
|
// 设置初始Z轴偏移时也要考虑深度强度
|
|
const finalZOffset = currentZOffset - (currentDepthStrength * 5 / 2);
|
|
currentDepthMesh.position.z = finalZOffset;
|
|
scene.add(currentDepthMesh);
|
|
|
|
// 只在初始化时重置相机位置
|
|
if (!needUpdate) {
|
|
resetView(currentDepthStrength);
|
|
}
|
|
}
|
|
|
|
needUpdate = true;
|
|
|
|
scene.add(ambientLight);
|
|
scene.add(camera);
|
|
|
|
progressDialog.close();
|
|
|
|
frameUpdate();
|
|
}
|
|
|
|
document.getElementById('screenshotButton').addEventListener('click', takeScreenshot);
|
|
|
|
// 修改截图函数
|
|
function takeScreenshot() {
|
|
const originalSize = {
|
|
width: renderer.domElement.width,
|
|
height: renderer.domElement.height
|
|
};
|
|
|
|
// 临时移除坐标轴和中心点
|
|
const axesHelper = scene.getObjectByName('axesHelper');
|
|
const centerPoint = scene.getObjectByName('centerPoint');
|
|
if (axesHelper) {
|
|
scene.remove(axesHelper);
|
|
}
|
|
if (centerPoint) {
|
|
scene.remove(centerPoint);
|
|
}
|
|
|
|
// 设置高分辨率
|
|
renderer.setSize(currentScreenshotSize, currentScreenshotSize);
|
|
camera.aspect = 1;
|
|
camera.updateProjectionMatrix();
|
|
renderer.render(scene, camera);
|
|
|
|
// 获取截图
|
|
const dataURL = renderer.domElement.toDataURL('image/png');
|
|
const link = document.createElement('a');
|
|
link.href = dataURL;
|
|
link.download = `screenshot_${currentScreenshotSize}x${currentScreenshotSize}.png`;
|
|
link.click();
|
|
|
|
// 恢复原始尺寸和重新添加坐标轴和中心点
|
|
renderer.setSize(originalSize.width, originalSize.height);
|
|
camera.aspect = 1;
|
|
camera.updateProjectionMatrix();
|
|
if (axesHelper) {
|
|
scene.add(axesHelper);
|
|
}
|
|
if (centerPoint) {
|
|
scene.add(centerPoint);
|
|
}
|
|
renderer.render(scene, camera);
|
|
}
|
|
|
|
// Quilts功能实现
|
|
function startQuilts() {
|
|
isQuiltsMode = true;
|
|
quiltsProgress = 0;
|
|
quiltsStartTime = Date.now();
|
|
quiltsCurrentFrame = 0;
|
|
quiltsIsRotating = true;
|
|
controls.enabled = false; // 禁用控制器
|
|
|
|
// 清空之前的截图
|
|
quiltsScreenshots = [];
|
|
|
|
// 保存当前相机位置
|
|
const currentY = camera.position.y;
|
|
const currentZ = camera.position.z;
|
|
const currentX = camera.position.x;
|
|
const radius = Math.sqrt(currentX * currentX + currentZ * currentZ);
|
|
|
|
// 计算起始和结束角度
|
|
const halfAngleRange = currentQuiltsAngleRange / 2;
|
|
const quiltsStartRotation = halfAngleRange;
|
|
const quiltsEndRotation = -halfAngleRange;
|
|
|
|
// 计算第一个目标角度
|
|
const totalFrames = currentQuiltsNum;
|
|
const angleStep = (quiltsEndRotation - quiltsStartRotation) / (totalFrames - 1);
|
|
quiltsTargetRotation = quiltsStartRotation;
|
|
|
|
// 设置初始位置
|
|
const radian = THREE.MathUtils.degToRad(quiltsStartRotation);
|
|
const x = Math.sin(radian) * radius;
|
|
const z = Math.cos(radian) * radius;
|
|
camera.position.set(x, currentY, z);
|
|
camera.lookAt(0, 0, 0);
|
|
controls.update();
|
|
}
|
|
|
|
function stopQuilts() {
|
|
isQuiltsMode = false;
|
|
quiltsIsRotating = false;
|
|
controls.enabled = true; // 启用控制器
|
|
|
|
// 获取当前iframe的ID
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const iframeId = urlParams.get('id');
|
|
|
|
// 发送所有截图给父窗口
|
|
if (quiltsScreenshots.length > 0) {
|
|
window.parent.postMessage({
|
|
type: 'quiltsComplete',
|
|
imgs: quiltsScreenshots,
|
|
id: iframeId
|
|
}, '*');
|
|
|
|
// 清空截图数组
|
|
quiltsScreenshots = [];
|
|
}
|
|
}
|
|
|
|
function updateQuilts() {
|
|
if (!isQuiltsMode) return;
|
|
|
|
const currentTime = Date.now();
|
|
const elapsed = currentTime - quiltsStartTime;
|
|
quiltsProgress = Math.min(elapsed / QUILTS_DURATION, 1);
|
|
|
|
if (quiltsIsRotating) {
|
|
// 计算当前旋转角度
|
|
const totalFrames = currentQuiltsNum;
|
|
const halfAngleRange = currentQuiltsAngleRange / 2;
|
|
const quiltsStartRotation = halfAngleRange;
|
|
const quiltsEndRotation = -halfAngleRange;
|
|
const angleStep = (quiltsEndRotation - quiltsStartRotation) / (totalFrames - 1);
|
|
const targetRotation = quiltsStartRotation + (angleStep * quiltsCurrentFrame);
|
|
|
|
// 使用相机绕物体旋转,保持水平旋转半径不变
|
|
const currentX = camera.position.x;
|
|
const currentZ = camera.position.z;
|
|
const radius = Math.sqrt(currentX * currentX + currentZ * currentZ); // 计算当前水平旋转半径
|
|
const currentAngle = THREE.MathUtils.radToDeg(Math.atan2(currentX, currentZ));
|
|
const targetAngle = targetRotation;
|
|
const newAngle = currentAngle + (targetAngle - currentAngle) * quiltsProgress;
|
|
|
|
// 更新相机位置,保持水平旋转半径不变
|
|
const radian = THREE.MathUtils.degToRad(newAngle);
|
|
const x = Math.sin(radian) * radius;
|
|
const z = Math.cos(radian) * radius;
|
|
|
|
// 保持Y坐标不变
|
|
const currentY = camera.position.y;
|
|
camera.position.set(x, currentY, z);
|
|
camera.lookAt(0, 0, 0);
|
|
controls.update();
|
|
|
|
if (quiltsProgress >= 1) {
|
|
// 完成当前角度的旋转
|
|
quiltsIsRotating = false;
|
|
takeQuiltsScreenshot();
|
|
|
|
// 准备下一个角度
|
|
quiltsCurrentFrame++;
|
|
if (quiltsCurrentFrame < currentQuiltsNum) {
|
|
quiltsProgress = 0;
|
|
quiltsStartTime = currentTime;
|
|
quiltsIsRotating = true;
|
|
} else {
|
|
stopQuilts();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 修改Quilts截图功能
|
|
async function takeQuiltsScreenshot() {
|
|
const originalSize = {
|
|
width: renderer.domElement.width,
|
|
height: renderer.domElement.height
|
|
};
|
|
|
|
// 临时移除坐标轴和中心点
|
|
const axesHelper = scene.getObjectByName('axesHelper');
|
|
const centerPoint = scene.getObjectByName('centerPoint');
|
|
if (axesHelper) {
|
|
scene.remove(axesHelper);
|
|
}
|
|
if (centerPoint) {
|
|
scene.remove(centerPoint);
|
|
}
|
|
|
|
// 确保在截图前完成渲染
|
|
renderer.setSize(currentScreenshotSize, currentScreenshotSize);
|
|
camera.aspect = 1;
|
|
camera.updateProjectionMatrix();
|
|
renderer.render(scene, camera);
|
|
|
|
// 获取截图数据
|
|
const dataURL = renderer.domElement.toDataURL('image/png');
|
|
quiltsScreenshots.push(dataURL);
|
|
|
|
// 恢复原始尺寸和重新添加坐标轴和中心点
|
|
renderer.setSize(originalSize.width, originalSize.height);
|
|
camera.aspect = 1;
|
|
camera.updateProjectionMatrix();
|
|
if (axesHelper) {
|
|
scene.add(axesHelper);
|
|
}
|
|
if (centerPoint) {
|
|
scene.add(centerPoint);
|
|
}
|
|
renderer.render(scene, camera);
|
|
}
|
|
|
|
// 更新旋转信息显示函数
|
|
function updateRotationDisplay() {
|
|
// 从相机获取旋转信息
|
|
const rotation = camera.rotation;
|
|
const euler = new THREE.Euler().setFromQuaternion(camera.quaternion);
|
|
const degrees = {
|
|
x: THREE.MathUtils.radToDeg(euler.x).toFixed(1),
|
|
y: THREE.MathUtils.radToDeg(euler.y).toFixed(1),
|
|
z: THREE.MathUtils.radToDeg(euler.z).toFixed(1)
|
|
};
|
|
rotationDisplay.textContent = `Rotation: X:${degrees.x}° Y:${degrees.y}° Z:${degrees.z}°`;
|
|
}
|