Как уменьшить размер файла в THREE.js GLTF-экспорте - PullRequest
0 голосов
/ 29 января 2019

Я создаю игру Mancala в THREE.js, используя довольно простые формы и физику для более интуитивного опыта, чем обычный вид сверху в 2D.Может быть, это излишне, но это life:)

Мне удалось собрать понравившуюся плату, но, поскольку она включает в себя скромное количество кода и циклов для сборки, я решил, что должен собрать ее отдельно и экспортироватьобъект как файл GLTF или GLB для загрузки в версию для клиента.Проблема в том, что функция GLTFExporter выплевывает файлы размером 3 или 4 МБ, даже в двоичном формате, что не является чрезвычайно сложной формой.(OBJ еще хуже.) Мой вопрос таков: что в объекте THREE.js может привести к тому, что файлы экспорта растут так быстро, и чем можно пожертвовать ради максимального уменьшения размера?

Фон:

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

enter image description here

После многих экспериментов с ThreeCSG я обнаружил, что намного проще использовать Элегантный RoundEdgeBox Пола Уэста (2.0) для внешней рамы вырезаем верхний и нижний края, затем включаем разделители между бункерами и большими бассейнами с простыми BoxGeometries:

enter image description here

Этот объектэкспорт в очень удобные 170Кб или около того в формате GLTF.

Чтобы округлить внутреннюю часть полостей, я использовал ExtrudeGeometry, чтобы создать дугу PI / 2, которая сливается с внутренней частью бункеров:

    // length is the height, size is the thickness
    let makeBorder = function(length, radius, size) {
        extrudeSettings.depth = length;
        let shape = new THREE.Shape();
        shape.moveTo(radius + size, 0 );
        shape.arc(-radius - size, 0, radius + size, 0, Math.PI / 2, false)
        shape.lineTo( 0, radius );
        shape.arc(0, -radius, radius, Math.PI / 2, 0, true)
        shape.lineTo( radius + size, 0 );

        let geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
        geometry.computeBoundingBox();
        return geometry;
    }

Слияние восьми из этих четверти дуг в размер боВдобавок к вертикальным и вертикальным краям бункеров вы получаете действительно хорошую кривизну:

enter image description here

Что НЕ приятно, так это наложение нескольких МБ информации наGLTF и GLB файлы.Я вполне уверен, что правильно сделал все очевидные вещи:

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

Просто глядя на версию экспорта в формате JSON (GLTF), я вижу несколько вещейв конце, о котором я не просил, как pbrMetallicRoughness в materials:

"materials": [
{
  "pbrMetallicRoughness": {
    "baseColorFactor": [
      0.6784313725490196,
      0.8470588235294118,
      0.9019607843137255,
      1
    ],
    "metallicFactor": 0.5,
    "roughnessFactor": 0.5
  }
}
]

Но я не думаю, что это добавляет много.Есть четыре BufferViews, все существенного размера.Это нормально и необходимо?

"bufferViews": [
{
  "buffer": 0,
  "byteOffset": 0,
  "byteLength": 35712,
  "target": 34962,
  "byteStride": 12
},
{
  "buffer": 0,
  "byteOffset": 35712,
  "byteLength": 35712,
  "target": 34962,
  "byteStride": 12
},
{
  "buffer": 0,
  "byteOffset": 71424,
  "byteLength": 35712,
  "target": 34962,
  "byteStride": 12
},
{
  "buffer": 0,
  "byteOffset": 107136,
  "byteLength": 23808,
  "target": 34962,
  "byteStride": 8
}
]

Прямо сейчас мой план атаки состоит в том, чтобы уменьшить выходной сигнал до одного бассейна и одного мусорного ведра, а затем клонировать и соединить их вместе на клиенте.Это не сложно, но хотелось бы, чтобы в этом не было необходимости.Учитывая, что эта фигура многократно повторяет одну и ту же подфигуру, нет ли способа сделать сжатый GLTF?

...