2016-06-08 40 views
0

我正在尝试在WebGL中编写一个非常小的工具,该工具允许我绘制UV'ed网格。到目前为止,挑战之一是试图找到一种方法将鼠标拾取位置转换为我应该在加载纹理中绘制的位置。有没有人有任何例子或可以推荐一些关于这方面的文献?将3D拾取转换为纹理投影?

回答

2

您正在寻找的“技巧”可能是THREE.Raycaster.setFromCamera()Here's a jsfiddle,它做了我认为你想要做的简单版本。它在一个画布中呈现包含纹理球体的简单场景,并将应用于该球体的纹理的副本放入另一个画布中。点击球体将在第二个画布上的纹理上的相应点上绘制一个红点。

有趣的要点是:

的init()我们定义了一个点击处理程序进行渲染的帆布,被称为clickCanvas。它通过点击事件的x和y坐标来getClickPosition()

function getClickPosition(n, x, y) { 
     var rect; 

     rect = n.getBoundingClientRect(); 
     return([ 
       (x - rect.left)/n.clientWidth, 
       (y - rect.top)/n.clientHeight 
     ]); 
} 

这转化的x和y坐标为0和1之间的UV-ISH有序对这些值的值被传递到projectLocation()

function projectLocation(x, y) { 
     var c, i, v, p; 

     // Bounds check our coords 
     if(x < 0) x = 0; 
     if(x > 1) x = 1; 
     if(y < 0) y = 0; 
     if(y > 1) y = 1; 

     // Convert our values from the range [0, 1] to the range [-1, 1] 
     v = new THREE.Vector2(); 
     v.x = x * 2 - 1; 
     v.y = (-y * 2) + 1; 

     raycaster.setFromCamera(v, camera); 
     i = raycaster.intersectObjects(scene.children, true); 
     if(i.length > 0) { 
       getLocation(i[0]); 
     } 
} 

这需要紫外线上下的坐标,将它们转换成1之间的值-1,这是什么THREE.Raycaster()要(在这个例子中这将是更清洁有getClickPosition()自动执行此操作,但在实际代码中,您可能需要点击DOM元素中的相对位置)。 raycaster计算出是否有任何东西与点击发生的位置(在“摄像机镜头”上)投射到场景中相交。从那里相交对象(如果有的话)被传递到的getLocation()

function getLocation(intersect) { 
     var uv; 

     uv = intersect.uv; 
     x = Math.round(uv.x * texture.image.width); 
     y = Math.round((1 - uv.y) * texture.image.height); 

     canvasCtx.lineWidth = 1; 
     canvasCtx.fillStyle = 'red'; 
     canvasCtx.fillRect(x - 1, y - 1, 2, 2); 
     canvasCtx.fill(); 
} 

交点对象包含交点的UV坐标。 getLocation()将这些转换为纹理中的XY坐标。