Три. js Объектная Сетка - PullRequest
1 голос
/ 23 апреля 2020

Я хочу нарисовать сетку с тремя. js так, чтобы, учитывая центр и размер объекта:

  1. Он динамически регулирует гранулярность (пространство между линиями сетки) по отношению к размеру объекта.
  2. Линии сетки не относятся к объекту

Я выполнил первое требование. Второй трудно объяснить, но, вероятно, его легче понять на примере: https://jsfiddle.net/rendoir/gua7qd0s

В этой демонстрации вы можете увидеть, что если вы нажмете 's', размер объект увеличивается, как и сетка. Разделение сетки изменяется в соответствии с порядком величины размера объекта.

Проблема 2) заключается в том, что положение сетки относительно положения объекта (они имеют одинаковый центр). Поэтому сетка всегда идеально соответствует объекту.
Я пытаюсь разрушить эту иллюзию, создавая впечатление, что сетка существует в мировом пространстве, начиная с источника мира и появляясь за объектом.
Наивным подходом было бы разработать сетку с размером, который мог бы охватывать объект, начиная с начала координат. Тем не менее, поскольку сцена и камера будут установлены c (в данном случае это не так), я хочу сетку, которой достаточно для размещения объекта (не нужно начинать с начала координат, поскольку объект может быть от этого), а количество делений (гранулярность между линиями сетки) все еще меняется в зависимости от его размера.

Я понимаю, что текущее решение первой проблемы может конфликтовать со второй проблемой, поэтому я ищу идеи или даже существующие решения, если таковые имеются.

Примечание. объект всегда четырехугольник. Нажав 'c', вы также можете изменить центр объекта.

Основной код находится в классе Grid:

let divisions = getDivisions(size);

let step = size / divisions;
let halfSize = size / 2;

let vertices = [];

for ( let i = 0, k = - halfSize + step; i < divisions - 1; i ++, k += step ) {

    vertices.push( - halfSize, k, 0, halfSize, k, 0 );
    vertices.push( k, - halfSize, 0, k, halfSize, 0 );

}
// ...
lineSegments.position.set(this.center.x, this.center.y, this.center.z);

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Для этой цели вы можете использовать шейдеры.

Связанные темы форума:

https://discourse.threejs.org/t/three-infinitegridhelper-anti-aliased/8377?u=prisoner849

https://discourse.threejs.org/t/how-to-achieve-this-material-effect-gif-image/1270?u=prisoner849

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x888888);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

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

var geom = new THREE.PlaneBufferGeometry();
var mat = new THREE.ShaderMaterial({
  vertexShader: `
    varying vec4 vPos;
    void main() {
        vPos = modelMatrix * vec4( position, 1.0 );
        gl_Position = projectionMatrix * viewMatrix * vPos;
    }
  `,
  fragmentShader: `
    //http://madebyevan.com/shaders/grid/
    
    #extension GL_OES_standard_derivatives : enable

    varying vec4 vPos;

    void main() {
      vec2 coord = vPos.xy;

      vec2 grid = abs(fract(coord - 0.5) - 0.5) / fwidth(coord);
      float line = min(grid.x, grid.y);

      gl_FragColor = vec4(vec3(1.0 - min(line, 1.0)), 1.0);
    }
`
});

var plane = new THREE.Mesh(geom, mat);
scene.add(plane);

var clock = new THREE.Clock();

renderer.setAnimationLoop(() => {
  let t = clock.getElapsedTime();
  let scale = 5 + (Math.sin(t) * 0.5 + 0.5) * 2;
  plane.scale.set(scale, scale, 1);
  plane.position.set(
    Math.cos(t),
    Math.sin(t),
    0
  );
  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>
1 голос
/ 23 апреля 2020

Можно сделать один из следующих вариантов:

let box = new THREE.Box3().setFromObject( theObject );

let sz = box.getSize(new THREE.Vector3())

let root = new THREE.Object3D();
let maxSz = Math.max(Math.max(sz.x,sz.y),sz.z)
root.scale.multiplyScalar( 1.0 / maxSz )

root.add( theObject )
scene.add(root);

Теперь ваш объект всегда будет масштабироваться так, чтобы его максимальный размер оси составлял 1.

Box3 (). SetFromObject действительно полезен, но он может иметь определенную стоимость в зависимости от того, сколько работы ТРИ нужно сделать, чтобы определить конечный размер объекта. Так что, возможно, избегайте называть это постоянно. object.localToWorld и .worldToLocal также очень полезны .. просто к сведению.

Также к сведению .. http://madebyevan.com/shaders/grid/ имеет несколько классных подходов к созданию сеточных шейдеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...