TkAstral3D/packages/sdk/lib/dxf/drawShare.ts
2025-10-04 23:36:07 +08:00

922 lines
29 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as THREE from "three";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TTFLoader } from "three/examples/jsm/loaders/TTFLoader.js";
// import { SSAARenderPass } from "three/examples/jsm/postprocessing/SSAARenderPass.js";
// import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
// import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
// import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
// import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js';
import {
addTriangleFacingCamera,
getBSplinePolyline, getBulgeCurvePoints,
mtextContentAndFormattingToTextAndStyle
} from "./drawUtils";
// @ts-ignore
import { parseDxfMTextContent } from "@dxfom/mtext";
import { Font } from "three/examples/jsm/loaders/FontLoader.js";
import { PickHelper } from "./pickHelper";
import { DrawRect } from "./drawRect";
import log from '@/utils/log/Logger';
let signal, middleObject;
let scene, helpScene, camera, renderer, inputElement, font, data;
// 渲染辉光图层
// let composer, finalComposer;
const BLOOM_SCENE = 10;
const bloomLayer = new THREE.Layers();
bloomLayer.set(BLOOM_SCENE);
// const DarkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });
// const materials = {};
let modules: any = {};
// TODO 当前解析模式会存在 data.blocks 中还有实体但未匹配解析的情况;
// 记录已经解析的 data.blocks,data.entities遍历完成后处理
let parsedBlocks: string[] = [];
// 渲染配置项 && 对比度颜色实体集合
let options = {
bgColor: 0x000000,
contrastColor: 0xffffff,
fontUrl:''
}, contrastEntity: any = [];
// canvas默认宽高
export const state = {
width: 500,
height: 500,
};
/**
* 离屏canvas和普通canvas共用的绘制图纸方法
* 优先级offScreenCanvas > canvas
*/
export function main(d) {
const { canvas, onComplete } = d;
signal = d.signal;
middleObject = d.middleObject;
state.width = canvas.width;
state.height = canvas.height;
inputElement = d.inputElement;
data = d.data;
// cad配置项
options = Object.assign(options, d.options);
options.bgColor = Number(options.bgColor);
options.contrastColor = options.bgColor === 0x000000 ? 0xffffff : 0x000000;
createLineTypeShaders();
renderer = new THREE.WebGLRenderer({
canvas,
powerPreference: "high-performance",
depth: false,
antialias: true,
});
// 第三个参数false代表不更新canvas dom style
renderer.setSize(canvas.width, canvas.height, false);
renderer.setClearColor(options.bgColor, 1);
renderer.toneMapping = THREE.ReinhardToneMapping;
// renderer.autoClear = false;
const loader = new TTFLoader();
loader.loadAsync(options.fontUrl).then(function (response) {
font = new Font(response);
init();
// OrbitControls mousemove事件中未调用chang事件所以需要一直渲染
renderLoop();
// 添加灯光
scene.add(new THREE.AmbientLight(0xffffff, 1));
// 后期通道
// initComposer();
const controls = new OrbitControls(camera, inputElement);
controls.target.x = camera.position.x;
controls.target.y = camera.position.y;
controls.target.z = 0;
controls.mouseButtons = { LEFT: THREE.MOUSE.PAN, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.ROTATE };
controls.enableRotate = false;
controls.update();
// 注册模块
modules.drawRect = new DrawRect(inputElement, helpScene, camera, signal, middleObject);
modules.drawRect.setControls(controls);
const pickPosition = new THREE.Vector2(0, 0);
modules.pickHelper = new PickHelper(scene, camera, BLOOM_SCENE);
clearPickPosition();
function getCanvasRelativePosition(event) {
const rect = inputElement.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
};
}
function setPickPosition(event) {
const pos = getCanvasRelativePosition(event);
pickPosition.x = (pos.x / state.width) * 2 - 1;
pickPosition.y = (pos.y / state.height) * - 2 + 1;
modules.pickHelper.pick(pickPosition);
}
function clearPickPosition() {
//不像鼠标总是有一个位置,如果用户停止触摸屏幕,我们想要停止。现在我们只取一个不太可能取到的值
pickPosition.x = - 100000;
pickPosition.y = - 100000;
}
inputElement.addEventListener('mousemove', setPickPosition);
inputElement.addEventListener('mouseout', clearPickPosition);
inputElement.addEventListener('mouseleave', clearPickPosition);
inputElement.addEventListener('touchstart', (event) => {
// 防止窗口滚动
event.preventDefault();
setPickPosition(event.touches[0]);
}, { passive: false });
inputElement.addEventListener('touchmove', (event) => {
setPickPosition(event.touches[0]);
});
inputElement.addEventListener('touchend', clearPickPosition);
// 加载完毕
onComplete && onComplete();
font = undefined;
data = undefined;
resize({ width: inputElement.width, height: inputElement.height });
});
}
function createLineTypeShaders() {
let ltype, type;
if (!data.tables || !data.tables.lineType) return;
const ltypes = data.tables.lineType.lineTypes;
for (type in ltypes) {
ltype = ltypes[type];
if (!ltype.pattern) continue;
ltype.material = createDashedLineShader(ltype.pattern);
}
}
function createDashedLineShader(pattern) {
let dashedLineShader: any = {},
totalLength = 0.0;
for (let i = 0; i < pattern.length; i++) {
totalLength += Math.abs(pattern[i]);
}
dashedLineShader.uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib['common'],
THREE.UniformsLib['fog'],
{
// @ts-ignore
'pattern': { type: 'fv1', value: pattern },
// @ts-ignore
'patternLength': { type: 'f', value: totalLength }
}
]);
dashedLineShader.vertexShader = [
'attribute float lineDistance;',
'varying float vLineDistance;',
THREE.ShaderChunk['color_pars_vertex'],
'void main() {',
THREE.ShaderChunk['color_vertex'],
'vLineDistance = lineDistance;',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}'
].join('\n');
dashedLineShader.fragmentShader = [
'uniform vec3 diffuse;',
'uniform float opacity;',
'uniform float pattern[' + pattern.length + '];',
'uniform float patternLength;',
'varying float vLineDistance;',
THREE.ShaderChunk['color_pars_fragment'],
THREE.ShaderChunk['fog_pars_fragment'],
'void main() {',
'float pos = mod(vLineDistance, patternLength);',
'for ( int i = 0; i < ' + pattern.length + '; i++ ) {',
'pos = pos - abs(pattern[i]);',
'if( pos < 0.0 ) {',
'if( pattern[i] > 0.0 ) {',
'gl_FragColor = vec4(1.0, 0.0, 0.0, opacity );',
'break;',
'}',
'discard;',
'}',
'}',
THREE.ShaderChunk['color_fragment'],
THREE.ShaderChunk['fog_fragment'],
'}'
].join('\n');
return dashedLineShader;
}
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(options.bgColor);
helpScene = new THREE.Scene();
const layersGroupMap: Map<string, THREE.Group> = new Map();
// 使用layers生成group
for (let layerName in data.tables.layer.layers) {
const layer = data.tables.layer.layers[layerName];
const group = new THREE.Group();
group.name = layerName;
group.visible = layer.visible;
layersGroupMap.set(layerName, group);
scene.add(group);
}
// 通过dxf数据创建场景
let entity, obj;
// 生成所有实体
for (let i = 0; i < data.entities?.length; i++) {
entity = data.entities[i];
obj = drawEntity(entity);
if (obj) {
if (layersGroupMap.has(entity.layer)) {
const parent = layersGroupMap.get(entity.layer) || scene;
parent.add(obj);
obj.name = `${entity.type}-${entity.handle || 'noHandle'}-${parent.children.length}`
} else {
scene.add(obj);
obj.name = `${entity.type}-${entity.handle || 'noHandle'}-${scene.children.length}`
}
}
obj = null;
}
// 2023-9-6:遍历所有剩下的未遍历的块,找出其中 INSERT/DIMENSION 类型的实体,进行解析.(非此类型就算解析位置也不正确)
// TODO 待删除
for (let blockName in data.blocks) {
const block = data.blocks[blockName];
if (parsedBlocks.includes(blockName) || !block.position || !block.entities) continue;
for (let j = 0; j < block.entities.length; j++) {
entity = block.entities[j];
if (entity.type == "INSERT" || entity.type == "DIMENSION") {
// TODO 容易栈溢出
// obj = this.drawEntity(entity);
//
// if (obj) {
// const bbox = new THREE.Box3().setFromObject(obj);
// if (isFinite(bbox.min.x) && (dims.min.x > bbox.min.x)) dims.min.x = bbox.min.x;
// if (isFinite(bbox.min.y) && (dims.min.y > bbox.min.y)) dims.min.y = bbox.min.y;
// if (isFinite(bbox.min.z) && (dims.min.z > bbox.min.z)) dims.min.z = bbox.min.z;
// if (isFinite(bbox.max.x) && (dims.max.x < bbox.max.x)) dims.max.x = bbox.max.x;
// if (isFinite(bbox.max.y) && (dims.max.y < bbox.max.y)) dims.max.y = bbox.max.y;
// if (isFinite(bbox.max.z) && (dims.max.z < bbox.max.z)) dims.max.z = bbox.max.z;
// this.scene.add(obj);
// }
// obj = null;
}
}
}
const aspectRatio = state.width / state.height;
const dims = new THREE.Box3().setFromObject(scene);
const upperRightCorner = { x: dims.max.x, y: dims.max.y };
const lowerLeftCorner = { x: dims.min.x, y: dims.min.y };
//const lowerLeftCorner = data.header.$EXTMIN; // X、Y 和 Z 图形范围左下角(在 WCS 中)
//const upperRightCorner = data.header.$EXTMAX; // X、Y 和 Z 图形范围右上角(在 WCS 中)
// 找出当前的视口范围
let vp_width = upperRightCorner.x - lowerLeftCorner.x;
let vp_height = upperRightCorner.y - lowerLeftCorner.y;
let center = {
x: vp_width / 2 + lowerLeftCorner.x,
y: vp_height / 2 + lowerLeftCorner.y
};
//let center = data.tables.viewPort.viewPorts[0].ucsOrigin;
// 将所有对象放入当前的查看器中
const extentsAspectRatio = Math.abs(vp_width / vp_height);
if (aspectRatio > extentsAspectRatio) {
vp_width = vp_height * aspectRatio;
} else {
vp_height = vp_width / aspectRatio;
}
const viewPort = {
bottom: -vp_height / 2,
left: -vp_width / 2,
top: vp_height / 2,
right: vp_width / 2,
center: {
x: center.x,
y: center.y
}
};
camera = new THREE.OrthographicCamera(viewPort.left, viewPort.right, viewPort.top, viewPort.bottom, 1, 19);
camera.position.z = 1;
camera.position.x = viewPort.center.x;
camera.position.y = viewPort.center.y;
camera.userData.viewPort = viewPort;
// 销毁中间变量
layersGroupMap.clear();
}
// function initComposer() {
// const pixelRatio = renderer.getPixelRatio();
//
// composer = new EffectComposer(renderer);
// composer.renderToScreen = false;
// composer.setPixelRatio(pixelRatio)
//
// let ssaaRenderPass = new SSAARenderPass(scene, camera);
// ssaaRenderPass.unbiased = false;
// ssaaRenderPass.sampleLevel = 2;
// composer.addPass(ssaaRenderPass);
//
// const bloomPass = new UnrealBloomPass(
// //参数一:泛光覆盖场景大小,二维向量类型
// new THREE.Vector2(inputElement.width, inputElement.height),
// //参数二bloomStrength 泛光强度,值越大明亮的区域越亮,较暗区域变亮的范围越广
// 1.5,
// //参数三bloomRadius 泛光散发半径
// 0,
// //参数四bloomThreshold 泛光的光照强度阈值,如果照在物体上的光照强度大于该值就会产生泛光
// 0
// );
// composer.addPass(bloomPass);
//
// const mixPass = new ShaderPass(
// new THREE.ShaderMaterial({
// uniforms: {
// baseTexture: { value: null },
// bloomTexture: { value: composer.renderTarget2.texture }
// },
// vertexShader: `
// varying vec2 vUv;
// void main() {
// vUv = uv;
// gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
// }
// `,
// fragmentShader: `
// uniform sampler2D baseTexture;
// uniform sampler2D bloomTexture;
// varying vec2 vUv;
// void main() {
// gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
// }`,
// defines: {}
// }), 'baseTexture'
// );
// mixPass.needsSwap = true;
//
// const outputPass = new OutputPass();
//
// finalComposer = new EffectComposer(renderer);
// finalComposer.addPass(ssaaRenderPass);
// finalComposer.addPass(mixPass);
// finalComposer.addPass(outputPass);
// }
// 图元选中
export function select({ modelOrName }) {
let model = modelOrName;
if (typeof modelOrName === 'string') {
model = scene.getObjectByProperty('name', modelOrName);
}
if (model) {
modules.pickHelper.select(model);
}
}
/** ------------------------------------------实体解析部分-------------------------------------------------------- **/
function getColor(entity) {
let color = options.contrastColor;//默认高对比度颜色
if (entity.color !== undefined) color = entity.color;
else if (data.tables && data.tables.layer && data.tables.layer.layers[entity.layer])
color = data.tables.layer.layers[entity.layer].color;
// 因为 scene.background = new THREE.Color(options.bgColor),所以黑色显示时改为白色
if (color == null || color === 0 || color === options.bgColor) {
color = options.contrastColor;
}
return color;
}
function drawEntity(entity) {
// 2023-9-6: 仅解析模型空间的实体
if (entity.inPaperSpace) return null;
let mesh;
switch (entity.type) {
case 'CIRCLE':
case 'ARC':
mesh = drawArc(entity);
break;
case 'LWPOLYLINE':
case 'LINE':
case 'POLYLINE':
mesh = drawLine(entity);
break;
case 'TEXT':
mesh = drawText(entity);
break;
case 'ATTDEF':
mesh = drawAttdef(entity);
break;
case 'ATTRIB':
mesh = drawAttrib(entity);
break;
case 'SOLID':
mesh = drawSolid(entity);
break;
case 'POINT':
mesh = drawPoint(entity);
break;
case 'INSERT':
mesh = drawBlock(entity);
break;
case 'SPLINE':
mesh = drawSpline(entity);
break;
case 'MTEXT':
// console.log("实体类型 MTEXT:", entity);
mesh = drawMtext(entity);
break;
case 'ELLIPSE':
mesh = drawEllipse(entity);
break;
case "HATCH":
mesh = drawHatch(entity);
break;
case 'DIMENSION':
const dimTypeEnum = entity.dimensionType & 7;
if (dimTypeEnum === 0) {
mesh = drawDimension(entity);
} else {
//console.log("不支持的维度类型: " + dimTypeEnum);
}
break;
default:
log.warn("不支持的实体类型: " + entity.type);
break;
}
if (mesh?.material && mesh.material?.color.getHex() === options.contrastColor) {
contrastEntity.push(mesh)
}
return mesh;
}
function drawArc(entity) {
let startAngle: number, endAngle: number;
if (entity.type === 'CIRCLE') {
startAngle = entity.startAngle || 0;
endAngle = startAngle + 2 * Math.PI;
} else {
startAngle = entity.startAngle;
endAngle = entity.endAngle;
}
//@ts-ignore
const curve = new THREE.ArcCurve(
0, 0,
entity.radius,
startAngle,
endAngle);
const points = curve.getPoints(32);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: getColor(entity) });
const arc = new THREE.Line(geometry, material);
arc.position.x = entity.center.x;
arc.position.y = entity.center.y;
arc.position.z = entity.center.z;
return arc;
}
function drawLine(entity) {
let points: THREE.Vector3[] = [];
let color = getColor(entity);
let material, lineType, vertex, startPoint, endPoint,
bulge, i, line;
if (!entity.vertices) return; //console.log('缺少顶点的实体.');
// 创建几何
for (i = 0; i < entity.vertices.length; i++) {
if (entity.vertices[i].bulge) {
bulge = entity.vertices[i].bulge;
startPoint = entity.vertices[i];
endPoint = i + 1 < entity.vertices.length ? entity.vertices[i + 1] : points[0];
let bulgePoints = getBulgeCurvePoints(startPoint, endPoint, bulge);
points.push.apply(points, bulgePoints);
} else {
vertex = entity.vertices[i];
points.push(new THREE.Vector3(vertex.x, vertex.y, 0));
}
}
if (entity.shape) points.push(points[0]);
// 设置材质
if (entity.lineType) {
lineType = data.tables.lineType.lineTypes[entity.lineType];
}
if (lineType && lineType.pattern && lineType.pattern.length !== 0) {
material = new THREE.LineDashedMaterial({ color: color, gapSize: 4, dashSize: 4 });
} else {
material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
}
const geometry = new THREE.BufferGeometry().setFromPoints(points);
line = new THREE.Line(geometry, material);
return line;
}
function drawText(entity) {
let geometry, material, text;
if (!font)
return log.warn('文本不支持没有Three.js字体加载的THREE.FontLoader!');
if (entity.text == null || entity.text == "") return null;
if (entity.textHeight == null || entity.textHeight == 0) return null;
// 当前使用的字体略宽,需要缩小一点
// xScale: 相对 X 比例因子 — 宽度
let fontSize = entity.xScale ? entity.xScale * entity.textHeight * 0.73 : entity.textHeight * 0.5;
geometry = new TextGeometry(entity.text, { font: font, depth: 0, size: fontSize || 100 });
if (entity.rotation) {
const zRotation = entity.rotation * Math.PI / 180;
geometry.rotateZ(zRotation);
}
material = new THREE.MeshBasicMaterial({ color: getColor(entity) });
text = new THREE.Mesh(geometry, material);
text.position.x = entity.startPoint.x;
text.position.y = entity.startPoint.y;
text.position.z = entity.startPoint.z;
return text;
}
function drawMtext(entity) {
const color = getColor(entity);
const textAndControlChars = parseDxfMTextContent(entity.text);
//Note: 目前只支持应用于所有mtext文本的单一格式
const content = mtextContentAndFormattingToTextAndStyle(textAndControlChars, entity, color);
/* 单行文本渲染模式 */
if (!font)
return log.warn('文本不支持没有Three.js字体加载的THREE.FontLoader!');
if (content.text == null || content.text == "") return null;
if (content.style.textHeight == null || content.style.textHeight == 0) return null;
const geometry = new TextGeometry(content.text, { font: font, depth: 0, size: content.style.textHeight || 100 });
if (entity.rotation) {
const zRotation = entity.rotation * Math.PI / 180;
geometry.rotateZ(zRotation);
}
if (entity.directionVector) {
const dv = entity.directionVector;
geometry.rotateZ(new THREE.Vector3(1, 0, 0).angleTo(new THREE.Vector3(dv.x, dv.y, dv.z)));
}
const material = new THREE.MeshBasicMaterial({ color });
const text = new THREE.Mesh(geometry, material);
text.position.x = entity.position.x;
text.position.y = entity.position.y;
text.position.z = entity.position.z;
return text;
/* TODO:多行文本渲染,拉近不显示 */
/*const txt = createTextForScene(content.text, content.style, entity, color,options.fontUrl);
if (!txt) return null;
console.log("MText txt:", txt);
// const group = new THREE.Object3D();
// group.add(txt);
return txt;*/
}
// @ts-ignore
function drawAttdef(entity) {
//console.log("drawAttdef:", entity);
}
// @ts-ignore
function drawAttrib(entity) {
//console.log("drawAttrib:", entity);
}
function drawSolid(entity) {
let material, verts,
geometry = new THREE.BufferGeometry();
const points = entity.points;
// verts = geometry.vertices;
verts = [];
addTriangleFacingCamera(verts, points[0], points[1], points[2]);
addTriangleFacingCamera(verts, points[1], points[2], points[3]);
material = new THREE.MeshBasicMaterial({ color: getColor(entity) });
geometry.setFromPoints(verts);
return new THREE.Mesh(geometry, material);
}
function drawPoint(entity) {
let geometry, material;
geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute([entity.position.x, entity.position.y, entity.position.z], 3));
const color = getColor(entity);
material = new THREE.PointsMaterial({ size: 0.1, color: new THREE.Color(color) });
return new THREE.Points(geometry, material);
// this.scene.add(point);
}
function drawBlock(entity) {
if (!data.blocks) return;
let block = data.blocks[entity.name];
if (!block) return null;
// 解析过的就存储起来,不再重复解析
parsedBlocks.push(entity.name);
if (!block.entities) return null;
const group = new THREE.Group();
if (entity.xScale) group.scale.x = entity.xScale;
if (entity.yScale) group.scale.y = entity.yScale;
if (entity.rotation) {
group.rotation.z = entity.rotation * Math.PI / 180;
}
if (entity.position) {
group.position.x = entity.position.x;
group.position.y = entity.position.y;
group.position.z = entity.position.z;
}
for (let i = 0; i < block.entities.length; i++) {
const childEntity = drawEntity(block.entities[i]);
if (childEntity) group.add(childEntity);
}
return group;
}
function drawSpline(entity) {
if (entity.controlPoints === undefined) return null;
const color = getColor(entity);
const points = getBSplinePolyline(entity.controlPoints, entity.degreeOfSplineCurve, entity.knotValues, 100, undefined);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
return new THREE.Line(geometry, material);
}
function drawEllipse(entity) {
const color = getColor(entity);
const xrad = Math.sqrt(Math.pow(entity.majorAxisEndPoint.x, 2) + Math.pow(entity.majorAxisEndPoint.y, 2));
const yrad = xrad * entity.axisRatio;
const rotation = Math.atan2(entity.majorAxisEndPoint.y, entity.majorAxisEndPoint.x);
const curve = new THREE.EllipseCurve(
entity.center.x, entity.center.y,
xrad, yrad,
entity.startAngle, entity.endAngle,
false, // Always counterclockwise
rotation
);
const points = curve.getPoints(50);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
// 创建要添加到场景中的最后一个对象
return new THREE.Line(geometry, material);
}
function drawHatch(entity) {
if (entity.isSolid) return
// TODO 未实现
}
function drawDimension(entity) {
if (!data.blocks) return;
// console.log("drawDimension", entity.block)
const block = data.blocks[entity.block];
// 解析过的就存储起来,不再重复解析
parsedBlocks.push(entity.block);
if (!block || !block.entities) return null;
const group = new THREE.Group();
// if(entity.anchorPoint) {
// group.position.x = entity.anchorPoint.x;
// group.position.y = entity.anchorPoint.y;
// group.position.z = entity.anchorPoint.z;
// }
for (let i = 0; i < block.entities.length; i++) {
const childEntity = drawEntity(block.entities[i]);
if (childEntity) group.add(childEntity);
}
return group;
}
/** ------------------------------------------实体解析结束-------------------------------------------------------- **/
// 设置图层可见性
export function setLayerVisible(data: { layerName: string, visible: boolean }) {
const group = scene.getObjectByName(data.layerName);
if (group) group.visible = data.visible;
}
// 调用modules里的方法
export function callModuleMethod(data: { moduleName: string, methodName: string }) {
const module = modules[data.moduleName];
if (module && module[data.methodName]) {
module[data.methodName](data);
}
}
// 相机复位
export function resetCamera() {
const viewPort = camera.userData.viewPort;
if (!viewPort) return;
camera.left = viewPort.left;
camera.right = viewPort.right;
camera.top = viewPort.top;
camera.bottom = viewPort.bottom;
camera.position.z = 1;
camera.position.x = viewPort.center.x;
camera.position.y = viewPort.center.y;
modules.drawRect.controls.target.x = camera.position.x;
modules.drawRect.controls.target.y = camera.position.y;
modules.drawRect.controls.target.z = 0;
modules.drawRect.controls.object.zoom = 1;
modules.drawRect.controls.update();
}
//let start;
export function resize({ width, height }) {
if (!camera || data) return;
const hscale = width / state.width;
const vscale = height / state.height;
state.width = width;
state.height = height;
camera.top = (vscale * camera.top);
camera.bottom = (vscale * camera.bottom);
camera.left = (hscale * camera.left);
camera.right = (hscale * camera.right);
camera.updateProjectionMatrix();
renderer.setSize(width, height, false);
// composer.setSize(width, height);
// finalComposer.setSize(width, height);
render();
}
//
// function darkenNonBloomed(obj) {
// if (obj.material && bloomLayer.test(obj.layers) === false) {
// materials[obj.uuid] = obj.material;
// obj.material = DarkMaterial;
// }
// }
//
// function restoreMaterial(obj) {
// if (materials[obj.uuid]) {
// obj.material = materials[obj.uuid];
// delete materials[obj.uuid];
// }
// }
export function render() {
renderer.autoClear = false;
// scene.traverse(darkenNonBloomed);
// composer.render();
// scene.traverse(restoreMaterial);
// finalComposer.render();
renderer.render(scene, camera);
renderer.render(helpScene, camera);
renderer.autoClear = true;
}
export function stopRender() {
renderer.setAnimationLoop(null)
}
export function renderLoop() {
renderer.setAnimationLoop(render)
}
export function helpRender() {
renderer.autoClear = false;
renderer.render(helpScene, camera);
}
export function dispose() {
data = undefined;
font = undefined;
renderer.setAnimationLoop(null)
renderer?.dispose();
scene.children.forEach((obj) => {
scene.remove(obj);
})
camera.remove();
scene.remove();
}
/** ---------------------------- 设置弹窗配置变化 ---------------------------------- */
export function changeClearColor(color: 0x000000 | 0xffffff) {
options.bgColor = color;
options.contrastColor = options.bgColor === 0x000000 ? 0xffffff : 0x000000;
scene.background = new THREE.Color(options.bgColor);
contrastEntity.forEach(mesh => {
if (!mesh.material || !mesh.material.color) return;
mesh.material.color = new THREE.Color(options.contrastColor);
})
}