улучшение точности радиопередачи в three.js - PullRequest
1 голос
/ 12 марта 2019

Я использую преобразование, чтобы привести луч от середины каждой грани сетки к самой сетке, чтобы найти локальную толщину.Интересно, что из-за расположения ячеек иногда луч проходит между треугольниками и не показывает правильную толщину.Кто-то упомянул мне проблему с точностью поплавка.Мне было интересно, если кто-нибудь знает, как улучшить мой код.Спасибо.

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100000);
camera.position.setScalar(500);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

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

var loader = new THREE.STLLoader();
loader.load('https://sos-ch-dk-2.exo.io/stl-upload-test/uploads/stl/5bd15fae89ff9a1cb7816af9/stl/hexagon.STL', function(geometry) {
  var material = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, vertexColors: THREE.VertexColors});
  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
  colorMesh(mesh);
});

function colorMesh(mesh) {

  //var minDist = 0.6;
	var colorArray = [];
  var raycaster = new THREE.Raycaster();
  var intersects = [];

  var pos = mesh.geometry.attributes.position;

  var ori = new THREE.Vector3();
  var dir = new THREE.Vector3();
  var trc = new THREE.Vector3();
  var a = new THREE.Vector3(),
    b = new THREE.Vector3(),
    c = new THREE.Vector3(),
    midPoint = new THREE.Vector3(),
    tri = new THREE.Triangle();
  var closest = new THREE.Vector3();

  var faces = pos.count / 3;
  for (let i = 0; i < faces; i++) {
    a.fromBufferAttribute(pos, i * 3 + 0);
    b.fromBufferAttribute(pos, i * 3 + 1);
    c.fromBufferAttribute(pos, i * 3 + 2);
    tri.set(a, b, c);
    tri.getMidpoint(ori);
    tri.getNormal(dir)
    raycaster.set(ori, dir.negate());
    intersects = raycaster.intersectObject(mesh);
		//minDist = Math.min(minDist, intersects[intersects.length > 1 ? 1 : 0].distance);
    minDist = intersects[intersects.length > 1 ? 1 : 0].distance;
    console.log(minDist);
    
    var col =  new THREE.Vector3(Math.floor((10/minDist)*255),Math.floor(0.01*minDist*255),0);	
    //var col =  new THREE.Vector3(0,0,0);	
    
    for (var j = 0;j<3;j++) {
      colorArray.push(col.x);
      colorArray.push(col.y);
      colorArray.push(col.z);
    }
    console.log(col);
  }
  var colors = new Uint8Array( colorArray );

  mesh.geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3,true ) );

	//helper = new THREE.VertexNormalsHelper( objects[0], 2, 0x00ff00, 1 );
				// scene.add(helper);
  //return minDist >= 0.6;
}


renderer.setAnimationLoop(() => {
  renderer.render(scene, camera)
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/loaders/STLLoader.js"></script>

образец изображения

1 Ответ

2 голосов
/ 14 марта 2019

Проблема в том, что Ray.js не рассматривает все возможные случаи. Фактически, он возвращает либо точку пересечения, либо ноль, которого недостаточно для решения вашей проблемы с ребрами.

Проблема: Когда луч пересекает сетку, возможны многие особые случаи:

  1. луч проходит точно через одну единственную вершину сетки -> в текущей реализации это будет сообщаться как ноль, или один, или два, или до N пересечений (зависит от того, как точность с плавающей запятой действует на каждую из N граней, основанных на этой вершине)

  2. луч проходит точно вдоль одной из граней ,

  3. луч проходит вдоль лица и в конце встречается с вершиной,

... и многие другие подобные ситуации, но вы поймете.


Существует способ значительно снизить риск попадания в такие ситуации: не используйте среднюю точку лица, вместо этого используйте случайную точку на лице.

Например:

// tri.getMidpoint(ori);

// get some random point on face
let r0 = 0.33 * Math.random();
let r1 = 0.33 * Math.random();
let r2 = 1.0 - r0 - r1;

let ori = new THREE.Vector3(
    r0*a.x + r1*b.x + r2*c.x,
    r0*a.y + r1*b.y + r2*c.y,
    r0*a.z + r1*b.z + r2*c.z
);
...