In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
Today, I will talk to you about how to use three.js to draw three-dimensional arrow lines, many people may not know much about it. In order to make you understand better, the editor has summarized the following content for you. I hope you can get something according to this article.
Demand: this demand is a rigid demand! In a subway scene to show the escape route, this route must have an indicator arrow, in order to draw this arrow, I spent no less than ten hours, finally made it, but there is always something wrong. My requirement for this arrow is that no matter the scene is zoomed in or out, the arrow should not be too large, too small to be seen clearly, and the shape cannot be changed, otherwise it will not look like an arrow.
Using three.js 's Line2.js and an open source library MeshLine.js
Part of the code:
DrawPath.js:
/ * draw the route * / import * as THREE from'.. / build/three.module.js';import {MeshLine, MeshLineMaterial, MeshLineRaycast} from'.. / js.my/MeshLine.js';import {Line2} from'.. / js/lines/Line2.js';import {LineMaterial} from'.. / js/lines/LineMaterial.js';import {LineGeometry} from'.. / js/lines/LineGeometry.js';import {GeometryUtils} from'.. / js/utils/GeometryUtils.js' Import {CanvasDraw} from'.. / js.my/CanvasDraw.js';import {Utils} from'.. / js.my/Utils.js';import {Msg} from'.. / js.my/Msg.js';let DrawPath = function () {let _ self = this; let _ canvasDraw = new CanvasDraw (); let utils = new Utils (); let msg = new Msg (); this._isDrawing = false; this._path = []; this._lines = [] This._arrows = []; let _ depthTest = true; let _ side = 0; let viewerContainerId ='# cc'; let viewerContainer = $(viewerContainerId) [0]; let objects; let camera; let turn; let scene; this.config = function (objects_, camera_, scene_, turn_) {objects = objects_; camera = camera_; turn = turn_; scene = scene_ This._oldDistance = 1; this._oldCameraPos = {x: camera.position.x, y: camera.position.y, z: camera.position.z}} this.start = function () {if (! this._isDrawing) {this._isDrawing = true; viewerContainer.addEventListener ('click', ray); viewerContainer.addEventListener (' mousedown', mousedown) ViewerContainer.addEventListener ('mouseup', mouseup);} msg.show ("Please click on the ground to draw a line");} this.stop = function () {if (this._isDrawing) {this._isDrawing = false; viewerContainer.removeEventListener (' click', ray); viewerContainer.addEventListener ('mousedown', mousedown); viewerContainer.addEventListener (' mouseup', mouseup) } msg.show ("stop drawing lines") } function mousedown (params) {this._mousedownPosition = {x: camera.position.x, y: camera.position.y, z: camera.position.z}} function mouseup (params) {this._mouseupPosition = {x: camera.position.x, y: camera.position.y, z: camera.position.z}} function ray (e) {turn.unFocusButton (); let raycaster = createRaycaster (e.clientX, e.clientY) Let intersects = raycaster.intersectObjects (objects.all); if (intersects.length > 0) {let point = intersects [0] .point; let distance = utils.distance (this._mousedownPosition.x, this._mousedownPosition.y, this._mousedownPosition.z, this._mouseupPosition.x, this._mouseupPosition.y, this._mouseupPosition.z); if (distance
< 5) { _self._path.push({ x: point.x, y: point.y + 50, z: point.z }); if (_self._path.length >1) {let point1 = _ self._ path[ _ self._path.length-2]; let point2 = _ self._ path[ _ self._path.length-1]; drawLine (point1, point2); drawArrow (point1, point2) }} function createRaycaster (clientX, clientY) {let x = (clientX / $(viewerContainerId). Width ()) * 2-1; let y =-(clientY / $(viewerContainerId). Height ()) * 2 + 1; let standardVector = new THREE.Vector3 (x, y, 0.5); let worldVector = standardVector.unproject (camera) Let ray = worldVector.sub (camera.position). Normalize (); let raycaster = new THREE.Raycaster (camera.position, ray); return raycaster;} this.refresh = function () {if (_ self._path.length > 1) {let distance = utils.distance (this._oldCameraPos.x, this._oldCameraPos.y, this._oldCameraPos.z, camera.position.x, camera.position.y, camera.position.z) Let ratio = 1; if (this._oldDistance! = 0) {ratio = Math.abs ((this._oldDistance-distance) / this._oldDistance)} if (distance > 5 & & ratio > 0.1) {console.log ("= DrawPath refresh = =") for (let I = 0; I
< _self._path.length - 1; i++) { let arrow = _self._arrows[i]; let point1 = _self._path[i]; let point2 = _self._path[i + 1]; refreshArrow(point1, point2, arrow); } this._oldDistance = distance; this._oldCameraPos = { x: camera.position.x, y: camera.position.y, z: camera.position.z } } } } function drawLine(point1, point2) { const positions = []; positions.push(point1.x / 50, point1.y / 50, point1.z / 50); positions.push(point2.x / 50, point2.y / 50, point2.z / 50); let geometry = new LineGeometry(); geometry.setPositions(positions); let matLine = new LineMaterial({ color: 0x009900, linewidth: 0.003, // in world units with size attenuation, pixels otherwise dashed: true, depthTest: _depthTest, side: _side }); let line = new Line2(geometry, matLine); line.computeLineDistances(); line.scale.set(50, 50, 50); scene.add(line); _self._lines.push(line); } function drawArrow(point1, point2) { let arrowLine = _self.createArrowLine(point1, point2); var meshLine = arrowLine.meshLine; let canvasTexture = _canvasDraw.drawArrow(THREE, renderer, 300, 100); //箭头 var material = new MeshLineMaterial({ useMap: true, map: canvasTexture, color: new THREE.Color(0x00f300), opacity: 1, resolution: new THREE.Vector2($(viewerContainerId).width(), $(viewerContainerId).height()), lineWidth: arrowLine.lineWidth, depthTest: _depthTest, side: _side, repeat: new THREE.Vector2(1, 1), transparent: true, sizeAttenuation: 1 }); var mesh = new THREE.Mesh(meshLine.geometry, material); mesh.scale.set(50, 50, 50); scene.add(mesh); _self._arrows.push(mesh); } function refreshArrow(point1, point2, arrow) { let arrowLine = _self.createArrowLine(point1, point2); var meshLine = arrowLine.meshLine; let canvasTexture = _canvasDraw.drawArrow(THREE, renderer, 300, 100); //箭头 var material = new MeshLineMaterial({ useMap: true, map: canvasTexture, color: new THREE.Color(0x00f300), opacity: 1, resolution: new THREE.Vector2($(viewerContainerId).width(), $(viewerContainerId).height()), lineWidth: arrowLine.lineWidth, depthTest: _depthTest, side: _side, repeat: new THREE.Vector2(1, 1), transparent: true, sizeAttenuation: 1 }); arrow.geometry = meshLine.geometry; arrow.material = material; } this.createArrowLine = function (point1, point2) { let centerPoint = { x: (point1.x + point2.x) / 2, y: (point1.y + point2.y) / 2, z: (point1.z + point2.z) / 2 }; let distance = utils.distance(point1.x, point1.y, point1.z, point2.x, point2.y, point2.z); var startPos = { x: (point1.x + point2.x) / 2 / 50, y: (point1.y + point2.y) / 2 / 50, z: (point1.z + point2.z) / 2 / 50 } let d = utils.distance(centerPoint.x, centerPoint.y, centerPoint.z, camera.position.x, camera.position.y, camera.position.z); if (d < 2000) d = 2000; if (d >10000) d = 10000; let lineWidth = 100d / 4000; / / console.log ("d =", d); let sc = 0.035 Var endPos = {x: startPos.x + (point2.x-point1.x) * sc * d / distance / 50, y: startPos.y + (point2.y-point1.y) * sc * d / distance / 50, z: startPos.z + (point2.z-point1.z) * sc * d / distance / 50} var arrowLinePoints = []; arrowLinePoints.push (startPos.x, startPos.y, startPos.z) ArrowLinePoints.push (endPos.x, endPos.y, endPos.z); var meshLine = new MeshLine (); meshLine.setGeometry (arrowLinePoints); return {meshLine: meshLine, lineWidth: lineWidth};} this.setDepthTest = function (bl) {if (bl) {_ depthTest = true; this._lines.map (line = > {line.material.depthTest = true) Line.material.side = 0;}); this._arrows.map (arrow = > {arrow.material.depthTest = true; arrow.material.side = 0;});} else {_ depthTest = false; this._lines.map (line = > {line.material.depthTest = false) Line.material.side = THREE.DoubleSide;}); this._arrows.map (arrow = > {arrow.material.depthTest = false; arrow.material.side = THREE.DoubleSide;}) }} / * revoke * / this.undo = function () {scene.remove (this._ Lines [this. _ lines.length-1]); scene.remove (this._ arrows [this. _ arrows.length-1]); _ self._path.splice (this._path.length-1,1); _ self._lines.splice (this._lines.length-1,1) _ self._arrows.splice (this._arrows.length-1,1);}} DrawPath.prototype.constructor = DrawPath;export {DrawPath}
Part of the code in show.js:
Let drawPath; / / draw the line drawPath = new DrawPath (); drawPath.config (objects, camera, scene, turn); $("# rightContainer"). Show (); $("# line-start"). On ("click", function (event) {drawPath.start ();}) On ("click", function (event) {drawPath.stop ();}); $("# line-undo") .on ("click", function (event) {drawPath.undo ();}); $("# line-show") .on ("click", function (event) {drawPath.refresh ();}); let depthTest = true On ("click", function (event) {if (depthTest) {drawPath.setDepthTest (false); depthTest = false;} else {drawPath.setDepthTest (true); depthTest = true;}}); setInterval () = > {drawPath & drawPath.refresh ();}, 100)
Effect picture:
There is still a problem:
Although in this effect picture, the scene is zoomed in and the arrow is a little big, the maximum size is still controlled, that is, there is something wrong with the shape, which may be a problem with the perspective.
The effect I expect should be like this, that is, no matter from any point of view, the arrowhead should not be deformed:
After reading the above, do you have any further understanding of how to use three.js to draw 3D arrowhead lines? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.