2017-02-06 1 views
0

Я пытаюсь объединить текстовые геометрии в Three.js (r84). Мне нужно сделать это с помощью multiMaterial и сохранить отдельные цвета для каждого текстового объекта. Вот живая демонстрация. https://jsfiddle.net/5oydk6nL/Слияние геометрий текста в Three.js при сохранении отдельных цветов материала

Спасибо.

var $win = $(window) , 
    $container = $('#webGL-container') , 

    scene , camera , cameraTarget , renderer , 
    pointLight , hex , 
    stats , rendererStats , 

    typeface = 'https://cdn.rawgit.com/redwavedesign/ca97268140e8a51633595cd34bb77f16/raw/46ae61687ac8e7e3af01ee2c983580f2b0b0809f/bebas_regular.json'; 



/* text objects */ 

var a = { 
    text: 'a' , 
    color: 'red' , 
    x: -90 
} 

var b = { 
    text: 'b' , 
    color: 'blue' , 
    x: -60 
} 

var c = { 
    text: 'c' , 
    color: 'green' , 
    x: -30 
} 

var d = { 
    text: 'd' , 
    color: 'yellow' , 
    x: 0 
} 

var e = { 
    text: 'e' , 
    color: 'purple' , 
    x: 30 
} 

var f = { 
    text: 'f' , 
    color: 'orange' , 
    x: 60 
} 

var g = { 
    text: 'g' , 
    color: 'aqua' , 
    x: 90 
} 




// array with all text objects 
var letters = [ a , b , c , d , e , f , g ]; 




function decimalToHex(d) { 

    var hex = Number(d).toString(16); 
    hex = "000000".substr(0, 6 - hex.length) + hex; 
    return hex.toUpperCase(); 

} 




function init() { 


    /* create scene, camera and renderer */ 
    scene = new THREE.Scene(); 
    camera = new THREE.PerspectiveCamera(40 , window.innerWidth/window.innerHeight , .1 , 1500); 
    renderer = new THREE.WebGLRenderer({ antialias: true }); 

    /* setup renderer */ 
    renderer.setClearColor('#ffffff'); 
    renderer.setSize(window.innerWidth , window.innerHeight); 
    renderer.shadowMap.enabled = true; 
    renderer.shadowMapSoft = true; 

    /* setup camera */ 
    camera.position.x = 0; 
    camera.position.y = 0; 
    camera.position.z = 500; 

    cameraTarget = new THREE.Vector3(0 , 0 , 0); 

    /* Lights */ 
    pointLight = new THREE.PointLight(0xffffff, 2); 
    pointLight.position.set(20 , -300 , 200); 
    scene.add(pointLight); 

    pointLight.color.setStyle('#EBEBEB'); 
    hex = decimalToHex(pointLight.color.getHex()); 


    // load each text object from the 'letters' array 
    $.each(letters , function(index , letter) { 


     var fontLoader = new THREE.FontLoader(); 


     // load font 
     fontLoader.load(typeface , function (font) { 


      var geometry = new THREE.TextGeometry(letter.text , { 

        font: font, 
        height: 8 , 
        size: 28 , 
        curveSegments: 4 , 
        bevelThickness: 1, 
        bevelSize: 1.5 , 
        bevelSegments: 3 , 
        bevelEnabled: true , 
        material: 0, 
        extrudeMaterial: 1 

      }); 


      var material = new THREE.MultiMaterial([ 
       new THREE.MeshPhongMaterial({ color: letter.color , shading: THREE.FlatShading }), // front 
       new THREE.MeshPhongMaterial({ color: letter.color , shading: THREE.SmoothShading }) // side 
      ]); 


      var mesh = new THREE.Mesh(geometry , material); 


      mesh.position.set(letter.x , 0 , 0); 


      // add text object to scene 
      scene.add(mesh); 


     }); 


    // end of each loop 
    }); 


    // add the rendered element to the page 
    $container.append(renderer.domElement); 


} 




function render() { 

    camera.lookAt(cameraTarget); 

    renderer.clear(); 

    renderer.render(scene , camera); 

} 



function animate() { 

    // begin Three.js stats utility 
    stats.begin(); 

    requestAnimationFrame(animate); 

    render(); 

    // update Threex stats plugin 
    rendererStats.update(renderer); 

    // conclude sample for Three.js stats testing 
    stats.end(); 

} 



// performance monitoring 

rendererStats = new THREEx.RendererStats(); 
rendererStats.domElement.style.position = 'absolute' 
rendererStats.domElement.style.left = '0px' 
rendererStats.domElement.style.bottom = '0px' 
document.body.appendChild(rendererStats.domElement); 

stats = new Stats(); 
    stats.showPanel(0); 
    document.body.appendChild(stats.domElement); 
    document.body.appendChild(stats.dom); 



// initialize 
init(); 

// animate 
animate(); 
+0

Не было бы проще сгруппировать все буквы, используя 'THREE.Group()'? – prisoner849

+0

Сгруппировав объекты, улучшающие производительность? Это было мое рассуждение о желании объединить геометрии. Я еще не использовал группу. Смогу ли я перенести отдельные объекты, если они были сгруппированы? – redwavedesign

+0

[http://stackoverflow.com/questions/41988213/three-js-merge-with-different-textures](http://stackoverflow.com/questions/41988213/three-js-merge-with-different-textures) читать комментарии от WestLangley там – prisoner849

ответ

0

Here an updated fiddle.

Несколько вещей, которые нужно добавить:

1) создать многосоставный и добавить материал для каждой буквы:

var material = new THREE.MeshPhongMaterial({ 
    color: letter.color, 
    shading: THREE.FlatShading 
}); 

multiMaterial.materials.push(material); 

2) добавить индекс материала на все грани каждой буквы:

for (var i = 0, il = geometry.faces.length; i < il; i++) { 
    geometry.faces[i].materialIndex = index 
} 

3) Перевести геометрию х к право с помощью матрицы преобразования:

geometry.applyMatrix(
    matrix.makeTranslation(letter.x, 0, 0) 
); 

4) Объединить каждую геометрию письмо в единую геометрию:

mergedGeometry.merge(geometry); 

Теперь у вас есть одна слиты геометрия:

enter image description here


Примечание: Попробуйте предотвратить использование jQuery внутри вашей скрипки в следующий раз, эта дополнительная библиотека не нужна для вашего примера. Также читайте here in these guidelines for more information.

+0

Не имеет смысла объединять геометрии, которые используют разные материалы. Обратите внимание, что у вас все еще есть 7 обратных вызовов. – WestLangley

+0

@WestLangley ОК, я просто ответил на вопрос, и этот код выполняет эту работу. Но меня интересует ваше мнение по этому поводу. Не могли бы вы объяснить, что является целью «THREE.MultiMaterial», если использовать его в таком случае? »Не имеет смысла» *? Существуют ли другие случаи, когда имеет смысл использовать этот класс? Не могли бы вы ответить в ответ. Было бы полезно, если бы вы предоставили дополнительную информацию об этом. – Wilt

+0

(1) 'MultiMaterial' существует как пользовательский интерфейс для поддержки загрузчиков, таких как' OBJLoader', которые поддерживают материальные группы. (2) Только один шейдер может использоваться одновременно графическим процессором, поэтому для каждого материала должен быть призыв к розыгрышу. (3) Может иметь смысл объединить геометрию, которая имеет один и тот же материал. – WestLangley

Смежные вопросы