Эффект рисования линии в трех js [duplicate]

Мой ответ о том, как синглтоны вредны, всегда «трудно сделать правильно». Многие из основополагающих компонентов языков - это синглоны (классы, функции, пространства имен и даже операторы), а также компоненты в других аспектах вычислений (localhost, маршрут по умолчанию, виртуальная файловая система и т. Д.), И это не случайно. Хотя они время от времени вызывают проблемы и разочарования, они также могут многое сделать намного лучше.

Два самых больших винта, которые я вижу: рассматривают его как глобальный & amp; неспособный определить замыкание Синглтона.

Все говорят о Синглтоне как о глобалах, потому что они в основном. Тем не менее, много (к сожалению, не все) плохости в глобальном мире не по своей природе не является глобальным, а тем, как вы его используете. То же самое касается Singletons. На самом деле больше, так как «единый экземпляр» действительно не означает «глобально доступный». Это скорее естественный побочный продукт, и, учитывая все плохое, что мы знаем, приходит из него, мы не должны так торопиться, чтобы использовать глобальную доступность. Когда программисты видят Singleton, они, похоже, всегда получают доступ к нему напрямую через свой метод экземпляра. Вместо этого вы должны перейти к нему так же, как и любой другой объект. Большинство кодов не должны даже знать, что он имеет дело с синглтоном (свободная связь, правда?). Если только маленький бит кода обращается к объекту, подобному глобальному, большой вред отменяется. Я рекомендую использовать его, ограничивая доступ к функции экземпляра.

Синтаксический контекст также очень важен. Определяющая характеристика Singleton заключается в том, что существует «только одна», но, по правде говоря, она «только одна» в каком-то контексте / пространстве имен. Они обычно являются одним из: по одному на поток, процесс, IP-адрес или кластер, но также могут быть по одному на процессор, машину, пространство имен языков / загрузчик классов / независимо, подсеть, Интернет и т. Д.

, менее распространенной ошибкой является игнорирование образа жизни Синглтона. Просто потому, что есть только один, это не означает, что Синглтон - это какой-то всемогущий «всегда был и всегда будет», и это вообще не желательно (объекты без начала и конца нарушают всевозможные полезные предположения в коде и должны использоваться только в самых отчаянных обстоятельствах.

Если вы избегаете этих ошибок, Singletons все еще может быть PITA, бит готов увидеть много худших проблем, которые значительно смягчены. Представьте себе сингл Java, то есть явно определяемый как один раз для загрузчика классов (что означает, что ему нужна политика безопасности потоков), с определенными методами создания и уничтожения и жизненным циклом, который диктует, когда и как они вызваны, и чей «экземплярный» метод имеет защиту пакета, поэтому к нему обычно обращаются через другие, неглобальные объекты. Все еще потенциальный источник проблем, но, безусловно, гораздо меньше проблем.

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

11
задан Wilt 8 March 2016 в 10:39
поделиться

3 ответа

Вы можете анимировать линию - или увеличить количество отображаемых точек - очень легко с помощью методов BufferGeometry и setDrawRange(). Однако вам нужно установить максимальное количество точек.

var MAX_POINTS = 500;

// geometry
var geometry = new THREE.BufferGeometry();

// attributes
var positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );

// draw range
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );

// material
var material = new THREE.LineBasicMaterial( { color: 0xff0000 } );

// line
line = new THREE.Line( geometry,  material );
scene.add( line );

Вы устанавливаете данные позиции с использованием шаблона, подобного этому:

var positions = line.geometry.attributes.position.array;

var x = y = z = index = 0;

for ( var i = 0, l = MAX_POINTS; i < l; i ++ ) {

    positions[ index ++ ] = x;
    positions[ index ++ ] = y;
    positions[ index ++ ] = z;

    x += ( Math.random() - 0.5 ) * 30;
    y += ( Math.random() - 0.5 ) * 30;
    z += ( Math.random() - 0.5 ) * 30;

}

Если вы хотите изменить количество точек, сделанных после первого рендеринга, сделайте следующее:

line.geometry.setDrawRange( 0, newValue );

Если вы хотите изменить значения данных позиции после первого рендера , вы устанавливаете флаг needsUpdate следующим образом:

line.geometry.attributes.position.needsUpdate = true; // required after the first render

Вот скрипка , показывающая анимированную строку, которую вы можете адаптировать к вашему прецеденту.

< hr>

EDIT: см. этот ответ для метода, который вам может понравиться лучше, особенно если линия состоит всего из нескольких точек.

three.js r. 84

32
ответ дан Community 18 August 2018 в 23:13
поделиться
  • 1
    MAX_POINTS = 500; означает, что если пользователь создает более 500 пунктов, он ломается, правильно? Лучший сценарий будет заключаться в том, что мне не нужно предопределять количество точек, которые я хочу добавить. Хотя ваше решение по-прежнему лучше, чем у меня, поскольку BufferGeometry обладает большей эффективностью в работе с памятью, и вы используете меньше обратных вызовов. – user3960875 15 July 2015 в 05:47
  • 2
    Это как сделать то, что вы хотите в рамках three.js. – WestLangley 15 July 2015 в 14:21
  • 3
    @WestLangley Может ли это быть адаптировано для использования LineDashedMaterial ?, Я хочу сделать что-то похожее, но с тире, я открою вопрос, если это возможно. – Neil 17 December 2015 в 12:05
  • 4
    @Neil Да. Вам нужно будет добавить дополнительный атрибут геометрии lineDistance для размещения LineDashedMaterial. – WestLangley 20 December 2015 в 00:43

Я обновил скрипт с событиями мыши и векторным массивом, если вы хотите набросать руки.

https://jsfiddle.net/w67tzfhx/40/

function onMouseDown(evt) {

    if(evt.which == 3) return;


    var x = ( event.clientX / window.innerWidth ) * 2 - 1;
    var y =  - ( event.clientY / window.innerHeight ) * 2 + 1;

    // do not register if right mouse button is pressed.

    var vNow = new THREE.Vector3(x, y, 0);
    vNow.unproject(camera);
    console.log(vNow.x + " " + vNow.y+  " " + vNow.z); 
    splineArray.push(vNow);

    document.addEventListener("mousemove",onMouseMove,false);
    document.addEventListener("mouseup",onMouseUp,false);
}
6
ответ дан user3325025 18 August 2018 в 23:13
поделиться

Нарисуйте строку в реальном времени

Здесь обновлена ​​скрипка , где я оптимизировал код из user3325025 его примера; В этом случае абсолютно не нужно обновлять все точки линии на рендере. Обновление требуется только onMouseMove (обновление конца строки) и onMouseDown (рисование новой точки):

// update line
function updateLine() {
  positions[count * 3 - 3] = mouse.x;
  positions[count * 3 - 2] = mouse.y;
  positions[count * 3 - 1] = mouse.z;
  line.geometry.attributes.position.needsUpdate = true;
}

// mouse move handler
function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  mouse.z = 0;
  mouse.unproject(camera);
  if( count !== 0 ){
    updateLine();
  }
}

// add point
function addPoint(event){
  positions[count * 3 + 0] = mouse.x;
  positions[count * 3 + 1] = mouse.y;
  positions[count * 3 + 2] = mouse.z;
  count++;
  line.geometry.setDrawRange(0, count);
  updateLine();
}
3
ответ дан Wilt 18 August 2018 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: