feat(All):Initial

This commit is contained in:
2025-10-04 23:36:07 +08:00
commit 2b4e5d2668
1321 changed files with 415958 additions and 0 deletions
+922
View File
@@ -0,0 +1,922 @@
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);
})
}