圆半径相交(像一个圆形光标刷)-三个js
Circular radius intersection (like a circular cursor brush) - Three js
我希望能够在圆形光标的半径内捕捉对象的面(如在绘画/photoshop中)。
我会告诉你它是什么https://jsfiddle.net/Shaggisu/w7ufmutr/9/
我不仅希望能够选择与鼠标点相交的单个面,而且希望能够选择可能在圆形半径内的所有面,我试图为该光标上传一些图像,但无法真正使其与jsfiddle中的外部文件一起工作。
我的问题是,是否有一些标准的方法来实现在指定半径内的多次选择/交叉,或者我是否应该设计一些代码,例如在特定时刻在鼠标点周围的周围面重复。
我对three.js还很陌生,所以我想问一些指导,特别是如果有一些可靠的方法来实现,任何提示都会很有帮助。
var brushTexture = THREE.ImageUtils.loadTexture( '/cur_circle.png' );
var brushMaterial = new THREE.SpriteMaterial( { map: brushTexture, useScreenCoordinates: true, alignment: THREE.SpriteAlignment.center } );
brushSprite = new THREE.Sprite( brushMaterial );
brushSprite.scale.set( 32, 32, 1.0 );
brushSprite.position.set( 50, 50, 0 );
scene.add( brushSprite );
//////////////////////////////////////////////////////////////////////
// initialize object to perform world/screen calculations
projector = new THREE.Projector();
// when the mouse moves, call the given function
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function onDocumentMouseDown( event )
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
event.preventDefault();
console.log("Click.");
// update the mouse variable
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( targetList );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
controls.enabled = false; // stops camera rotation
console.log("Hit @ " + toString( intersects[0].point ) );
// change the color of the closest face.
intersects[ 0 ].face.color.setRGB( 0.8 * Math.random() + 0.2, 0, 0 );
intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}
}
function onDocumentMouseMove( event){
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
brushSprite.position.set( event.clientX, event.clientY, 0);
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( targetList );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
console.log("Hit @ " + toString( intersects[0].point ) );
// change the color of the closest face.
intersects[ 0 ].face.color.setRGB( 0.8 * Math.random() + 0.2, 0, 0 );
intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
}
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
}
function onDocumentMouseUp( event){
event.preventDefault();
document.removeEventListener( "mousemove", onDocumentMouseMove);
controls.enabled = true;
}
该代码是我用于实践的stemkoskis github的修改版本。我已经对它进行了一些扩展,用于交叉事件和连续选择的相机管理,但半径内多个面的选择是我现在最感兴趣的。
你可以在javascript中这样做,修改顶点颜色,就像你在示例中做的那样,但你会很快受到多边形数量的限制。
也就是说,把你的画笔想象成一个锥体,从光线开始。原点和射线方向延伸。笔刷的半径决定了圆锥体的半径
- 遍历每个顶点。
- 对于每一个,得到顶点到射线线之间的最小距离。
- 根据这个顶点和Ray.origin之间的距离获得画笔/圆锥体的半径
- 如果最小距离小于圆锥体半径,则顶点处于"内"状态。你也可以处理距离来创建一个平滑的画笔。
应该是这样的,有点像伪代码,你可能需要适应ThreeJs的数学库:
// Important, Ray origin and direction must be defined in the same space a vertices positions
// You may need to transform ray origin and direction in object local space.
// get the length of Ray.direction
// may be useless if 'direction' is normalized
var rayDirLenSq = ray.direction.length();
rayDirLenSq *= rayDirLenSq;
var brushRadius = 10.0;
for( var i=0;i< vertices.length;i++){
// get the vertex
var v = vertices[i];
var vdir = v.sub( ray.origin );
var dot = vdir.dot( ray.direction ) / rayDirLenSq;
if( dot < 0 ){
// handle vertices behind the camera if needed
}
// v2 : projection of the vertex onto ray line
var v2 = ray.direction.clone().multiplyScalar( dot );
// v3 : projection -> vertex
var v3 = vdir.subtract( v2 )
// dist is the distance between the vertex and the ray line
var dist = v3.length()
// 0 when vertex is at the brush border
// 1 when vertex is in the brush center
var paintingFactor = Math.max(0.0, 1.0 - dist/brushRadius )
}
根据你想要的,你可以存储每个顶点的绘画因子来获得每个面的平均因子。或者你可以独立修改每个顶点的顶点颜色,以在你的脸上获得渐变…
我没有测试代码,它可能包含一些错误:)
更高级的方法
你也可以使用纹理来绘制。你将摆脱顶点(和javascript)的限制。你将能够用纹理刷绘制,并在三角形内绘制细节(没有更多的顶点颜色)。
原则:你需要uv数据和纹理+ FBO为你的每个网格。
在预传中,对于每个网格,将其渲染到其uvs坐标中的Fbo
gl_Position = vec4( UVs*2.0-1.0, 0.0, 1.0 );
为片段着色器提供worldSpace顶点位置,这样您就可以访问对象纹理的每个像素的世界空间位置。
vVertexPosition = modelMatrix * aPosition;
在你的片段着色器中使用vVertexPosition,你可以使用与javascript相同的方法来获得每个像素的brushFactor。你甚至可以在基于光线的自定义投影矩阵中投影这个世界空间像素位置,以获得画笔纹理中像素的uv坐标,并使用纹理刷进行绘制。
- 如何使用JS捕捉带有垂直线的自定义图像光标
- d3.js-当鼠标悬停在SVG容器上的这些元素上时,我如何设置光标
- interact.js光标没有更改
- 在表单输入中键入.js闪烁光标时遇到问题
- Angular JS在两个文本字段之间更改光标时收到警报
- 键入.js脚本在iPhone6中不起作用,如果任何单词将在该行完成,在这种情况下,另一个单词不键入,仅显示光标
- 如何在 js 和 css3 中使用鼠标光标单击实现滚动图像
- Node.js:防止光标换行
- 在phantom.js中显示鼠标光标
- 如何在d3.js中根据需要更改光标
- Meteor.js:返回一个光标的非反应快照
- 用光标拖动使d3.js数据图旋转
- 如何在wysiwyg编辑器中按需隐藏光标闪烁符(插入符号)?(redector.js)
- Vue.js v-html contenteditable防止dom刷新,以防止光标/插入符号跳转
- 更改PIXI.js中的默认光标样式
- 如何知道光标位于pixi.js中的哪个对象
- HTML5 / JS:将光标锁定在canvas元素中
- 圆半径相交(像一个圆形光标刷)-三个js
- D3.js缩放只工作时,光标在像素的图形
- 为什么IE 8会让这个JS的光标跳到文本区域的末尾