Лучший способ обновить геометрию THREE.Points - PullRequest
0 голосов
/ 18 мая 2018

У меня есть модель блендера, на которой есть несколько ключей формы.Я экспортирую эту модель и использую ее в 3js.Допустим, это куб.Затем я создаю Three.Points, который рисует маленькие сферы на вершинах этой модели (т.е. Cube).

var cube = loadGLTFFromBlender(gltfFile); // This loads the model
var points = new THREE.Points(cube.geometry, pointMaterial); //got my points

Теперь, используя morphTargets, я анимирую куб.Пока все хорошо.

//Some code that uses the shapee keys 
cube.morphTargetInfluences[0] = 0.2; // <-- I animate this value

, но я ожидал, что точки также будут изменяться / анимироваться, поскольку точки используют одну и ту же геометрию.Но, похоже, не работает из коробки.

Некоторые из Google предположили, что морфинг происходит на уровне графического процессора, а данные геометрии в объекте не изменяются.В одном из вопросов StackOverflow ( Three.js: Получить обновленные вершины с морфируемыми целями ), @WestLangley предложил сделать те же самые обновления Geometry на CPU и затем использовать его.

Мои вопросы:

  1. Существуют ли другие варианты решения этой проблемы.
  2. Вычисление морфа ЦП кажется медленнее, и я пытаюсь увидеть, есть лиДругой способ синхронизировать мои Three.Points с морфированным кубом?Куб анимирован с помощью morphtargets, и я ожидаю, что Three.Points сделают то же самое.

Полагаю, # 1 - это не вариант, если анимации клавиш формы в Blender более активны?

В идеале может помочь что-то вроде следующего:

cube.morphTargetInfluences[0] = 0.2; // <-- I animate this value
var morphedGeometry = getMorphedGeometry(cube);
syncPointsGeometry(morphedGeometry); 

1 Ответ

0 голосов
/ 18 мая 2018

Отвечая на мой собственный вопрос, если это поможет другим в будущем.

Мне удалось найти пару решений:

  1. На основе процессора (медленно) - использование функции для копирования морфов в позиции

        function updatePointsGeometry(points,weight) {
            if (!points.geometry.attributes.morphTarget0) {
                return;
            }
            for (var i = 0; i < points.geometry.attributes.position.count; i++) {
                points.geometry.attributes.position.array[i+0] =  weight * points.geometry.attributes.morphTarget0.array[i+0];
                points.geometry.attributes.position.array[i+1] =  weight * points.geometry.attributes.morphTarget0.array[i+1];
                points.geometry.attributes.position.array[i+2] =  weight * points.geometry.attributes.morphTarget0.array[i+2];
            }
            points.geometry.attributes.position.needsUpdate = true;
        }
    
  2. на основе графического процессора (рекомендуется) - использование пользовательского шейдера, который использует морф-цели и морфинфлюенс для изменения точек

            var shaderPoint = THREE.ShaderLib.points;
            var uniforms = THREE.UniformsUtils.clone(shaderPoint.uniforms);
            uniforms.map.value = imageTexture;
            uniforms.size.value = 10;
            //Custom Shader
            customPointMaterial = new THREE.ShaderMaterial({
                uniforms: uniforms,
                morphTargets: true,
                defines: {
                    USE_MAP: ""
                },
                transparent: false,
                opacity: 1,
                alphaTest: 0.5,
                fog: false,
                vertexShader: document.getElementById( 'vertexShader' ).textContent,
                fragmentShader: shaderPoint.fragmentShader
            });
            //copy over the morph data from original geometry to the points
            myPoints = new THREE.Points(mesh.geometry, customPointMaterial);
            myPoints.morphTargetInfluences = mesh.morphTargetInfluences;
            myPoints.morphTargetDictionary = mesh.morphTargetDictionary;
    

А вот вершинный шейдер

    uniform float size;
    uniform float scale;
    uniform float morphTargetInfluences[ 4 ];

    #include <common>
    #include <color_pars_vertex>
    #include <fog_pars_vertex>
    #include <shadowmap_pars_vertex>
    #include <logdepthbuf_pars_vertex>
    #include <clipping_planes_pars_vertex>
    void main() {
        #include <color_vertex>
        #include <begin_vertex>
        #include <project_vertex>
        #ifdef USE_SIZEATTENUATION
            gl_PointSize = size * ( scale / - mvPosition.z );
        #else
            gl_PointSize = size;
        #endif
        vec3 morphed = vec3( 0.0 , 0.0 , 0.0 );
        morphed += ( morphTarget0 - position ) * morphTargetInfluences[0];
        morphed += position;
        gl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );
        #include <logdepthbuf_vertex>
        #include <clipping_planes_vertex>
        #include <worldpos_vertex>
        #include <shadowmap_vertex>
        #include <fog_vertex>
    }
...