当前位置: 首页 > 知识库问答 >
问题:

如何将一个矩形投射到网格/地形对象上,作为一个选择的选框?(在Three.js中)

燕青青
2023-03-14

目前我正在检测拖动的开始和结束,并在全局XZ平面中画出一个矩形,但我更希望它与表面齐平。

目前看来是这样的;

然而,我的目标是更像这样的东西;

我想知道我是否错过了使用核心的three.js特性实现这一点的一些明显方法。

总是有蛮力的方法,在矩形的周长周围间隔地投射射线,并创建一系列线段来近似投影的矩形,但我在想是否有一个原生的方法

(这周我才刚开始看Three.js,所以我可能错过了一些明显的东西……尽管我花了最后一天的时间做实验,运气也不太好)

更新

基于@Prisoner849的建议,我将他的代码与Terrain demo混合在一起,看起来效果很好。

    varying vec2 vPos;

    void main() {
      vec2 Ro = size * .5;
      vec2 Uo = abs( vPos - center.xz ) - Ro;

      vec3 c = mix(vec3(1.), vec3(1.,0.,0.), float(enabled && (abs(max(Uo.x,Uo.y)) < lineHalfWidth)  ));

      gl_FragColor = vec4(c, float(enabled && (abs(max(Uo.x,Uo.y)) < lineHalfWidth)  ));
    }

  `;

代码需要大量清理,需要旋转选框以匹配相机视角,如果有ctrl-click添加到选择集,等等,那就不错了。

但原则上碎片着色器运行良好...

共有1个答案

明正德
2023-03-14
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 5, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var geom = new THREE.PlaneGeometry(20, 20, 10, 10);
geom.vertices.forEach(v => {
  v.z = THREE.Math.randFloat(-1, 1);
});
geom.rotateX(-Math.PI * .5);
geom.computeFaceNormals();
geom.computeVertexNormals();

var uniforms = {
  center: {
    value: new THREE.Vector3()
  },
  size: {
    value: new THREE.Vector2(1, 1)
  },
  lineHalfWidth: {
    value: 0.1
  }
}

var matShader = new THREE.ShaderMaterial({
  uniforms: uniforms,
  vertexShader: vertShader,
  fragmentShader: fragShader
});

var matWire = new THREE.MeshBasicMaterial({
  color: "gray",
  wireframe: true
});

var obj = THREE.SceneUtils.createMultiMaterialObject(geom, [matShader, matWire]);

scene.add(obj);

var gui = new dat.GUI();
gui.add(uniforms.size.value, "x", .5, 5.0).name("size.x");
gui.add(uniforms.size.value, "y", .5, 5.0).name("size.y");
gui.add(uniforms.lineHalfWidth, "value", .05, 2.0).name("line half-width");

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects = [];
var point = new THREE.Vector3();

window.addEventListener("mousemove", function(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObject(obj, true);
  if (intersects.length === 0) return;
  obj.worldToLocal(point.copy(intersects[0].point));
  uniforms.center.value.copy(point);

}, false);


render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/0949e59f/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/0949e59f/examples/js/utils/SceneUtils.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/0949e59f/examples/js/libs/dat.gui.min.js"></script>
<script>
  var vertShader = `
    varying vec2 vPos;
    void main() {
      vPos = position.xz;
      gl_Position = projectionMatrix *
                    modelViewMatrix *
                    vec4(position,1.0);
    }
  `;

  var fragShader = `
    uniform vec3 center;
    uniform vec2 size;
    uniform float lineHalfWidth;
    
    varying vec2 vPos;
    
    void main() {
      vec2 Ro = size * .5;
      vec2 Uo = abs( vPos - center.xz ) - Ro;
      
      vec3 c = mix(vec3(1.), vec3(1.,0.,0.), float(abs(max(Uo.x,Uo.y)) < lineHalfWidth));
      
      gl_FragColor = vec4(c, 1.  );
    }
    
  `;
</script>
 类似资料:
  • 我正在学习python和pygame,我正在尝试制作一个纸牌游戏;我已经做了基本的逻辑,但是我正在努力使用一个简单的GUI。我需要有一个玩家能够从选秀行选择一张牌,并将其放在他们的6x4“棋盘”上。为此,我绘制了如下矩形: 但是现在我被卡住了,因为我不知道如何让玩家“选择”一个位置来放所选的牌(我假设它会以同样的方式被选择,只是更早)。我读了关于碰撞的文章,并考虑做一个手册“如果鼠标在这里,这就是

  • 在上面的图片中,我展示了两个矩形 矩形1,其x可以从-900到13700不等,Y可以从-600到6458 矩形2,其坐标X可以从0到3000变化,而y可以从0到2000变化 同样:矩形2的起点位于左上角位置(0,0),而矩形1的起点位于左上角位置(宽度/2,高度/2)。 我需要做的是:使用缩放或平移将矩形1的点转换为矩形2的点。 那么,为了将矩形1的坐标转换为矩形2的坐标,< code>x和< c

  • 问题内容: 创建哪一个将坐标从一个矩形映射到另一个矩形(给出浮动/双矩形)的最简单方法是什么? 更新1 矩形可以完全不同。例如[(0,0)-(1,1)]和[(150,-14)-(-1000,-14.1)]。并且转换应该统一转换。例如,矩形角应一一变换。例如,坐标(0,0)应该变成(150,-14)。 更新2 我需要对象,而不仅仅是计算。因为我想将其应用于对象。我也想以一些简单转换的串联形式。 更新

  • 问题内容: 我希望能够通过鼠标事件在matplotlib图上绘制选择区域。我没有找到有关如何使用python的信息。 最后,我希望能够在用matplotlib底图创建的地图上用鼠标绘制感兴趣的区域并检索角坐标。 有人有想法,例如参考吗? 谢谢, 格雷格 问题答案: Matplotlib提供了自己的。matplotlib页面上有一个示例,您可以根据需要进行调整。 简化版本如下所示:

  • 我有一个点[xmin,ymin,xmax,ymax]的列表,每个点都按黑点显示 请注意,有许多这样的矩形,如图像所示。红色的应检测删除,绿色的应保留。 输入是 n 矩形 输出是覆盖区域和它覆盖的矩形 id 。最好给出一些算法和解释。

  • 这更多的是一个方法问题,而不仅仅是技术问题。 我有一个生成的球体,分解成六边形作为一个网格。每一个六边形瓷砖都是一种不同的地形,例如,山,丘陵,海洋,飞机等。我想在3D中把每一种地形类型画成几个网格的集合,代表一种相应的地形类型。 现在最大的问题是如何在运行时将地形网格调整到每个六边形面,这取决于地形类型,在运行时地形类型也会发生变化,例如,地形变形。同时,考虑到六边形并不是完全正则或相等的。 缩