Как дублировать одну 3D модель несколько раз на странице?

Есть одна 3D модель, в будущем её нужно будет дублировать много раз, но ТЕКСТУРА будет меняться. При попытке дублировать <.script> ничего не работает.

Как можно это реализовать? 3D модель сделана через Three.js введите сюда описание изображения

   <script>
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(10, window.innerWidth / window.innerHeight, 0.1, 50);
    camera.position.z = 20;
    camera.position.y = 1.5;
    camera.position.x = 0;

    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setClearColor(0x000000, 0);
    renderer.setSize(200, 300);
    renderer.domElement.setAttribute("id", "Minecraft3D0bj");
    document.getElementsByClassName('skin_one')[0].insertBefore(renderer.domElement, document.getElementsByClassName('skin_one')[0].firstChild);
    var light = new THREE.HemisphereLight(0xFFFFFF, 0xFFFFFF, 1.41);
    scene.add(light);
    let loader = new THREE.GLTFLoader();
    let obj = null;
    loader.load('/Стив.gltf', function (gltf) {
        obj = gltf;
        obj.scene.scale.set(4.5, 1.5, 4.5);
        scene.add(obj.scene);
    });

    function animate() {

        requestAnimationFrame(animate);
        if (obj)
            obj.scene.rotation.y += 0.020;

        renderer.render(scene, camera);
    }
    animate();
    </script>
body {
  height: inherit;
  margin: 0 auto;
  padding: 0 auto;
  width: var(--layout-width);
  height: var(--header-height);
  --layout-width: 95%;
  height: 100%;
  background: rgb(26, 26, 26);
  flex-direction: row;
  display: flex;
}

.block {
  display: flex;
  width: 200px;
  height: 300px;
  margin: 15px;
  justify-content: center;
  align-items: center;
}

.block .skin {
  display: flex;
  position: absolute;
  justify-content: center;
  align-items: center;
  width: 200px;
  height: 300px;
  background: rgb(30, 30, 30);
  background: linear-gradient( 140deg,  rgba(30, 30, 30, 0.294) 0%,  rgba(17, 17, 17, 0.5) 100% );
  border: 2.1px solid rgb(70, 70, 70);
  border-radius: 10px;
  -webkit-box-shadow: 0px 2px 6px 3px #00000065;
  box-shadow: 0px 2px 6px 3px #0000004f;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js "></script>
</head>
<body>
<div class="block">
    <div class="skin">
    </div>
</div>
<div class="block_two">
    <div class="skin_two">
    </div>
</div>
</body>
</html>


Ответы (1 шт):

Автор решения: Хацкер

Вот упрощенная выдержка кода из моего проекта:

<script>
models = {
  build:{//модели без скелетной анимации
    home:{
      'href':'home.glb',
      'name':'home',
      'status':'not loaded',
      'model':undefined,
      'count':'0'
   },
  },
  units:{//модели с использованием скелетной анимации - их чуточку сложнее копировать
    human:{
      'href':'human.glb',
      'name':'human',
      'status':'not loaded',
      'model':undefined,
      'count':'0'
    },
  },
}

function loadModel(type, name){
  loader.load('models/'+models[type][name].href, function(gltf){
  
    models[type][name].status = 'loaded';
    if(type == 'build'){
       models[type][name].model = gltf.scene.children[0];// здесь, 
//сохраняется непосредственно НЕ сцена 3d объекта, а его Mesh потомок, в 
//противном случае используемый мной метод копирования объекта может ругаться 
//- требовать Mesh объект для клонирования. у сцены объекта могут быть 
//несколько потомков, зачастую это свой собственный источник света, проверить 
//под каким индексом идет Mesh вашего объекта можете с помощью консоли 
// console.log(gltf.scene);
       gltf.scene.children[0].name = models[type][name].name;
     }
     else if(type == 'units'{ //здесь же, наоборот,
  //копируется весь файл, это необходимо для сохранения скелетных анимаций
       models[type][name].model = gltf;
       gltf.scene.name = models[type][name].name;
     }
  });
}
function startLoader(){
  for(var type in models){
    for(var name in models[type]){
      if(models[type][name].status == 'not loaded') loadModel(type, name);
    }
  }
}
startLoader();
function addBuild(type, name){
  var newBuild = models[type][name].model.clone();
  models[type][name].count += 1;
  var newName = models[type][name].name + models[type][name].count;
  newBuild.name = newName; 
  scene.add(newBuild);
}
$('#addBuild').click(function(){//не знаю используете ли вы jQury...
//я привязал эти события к клику, для того чтобы они не сработали ДО того, 
//как все модели будут загружены, но вы можете воспользоваться
//менеджером загрузок THREE.JS
  addBuild('build', 'home');
});
 //до смены непосредственно текстуры объекта я еще не дошел (не приходилось пока),
//но думаю принцип такой же (клонировать, изменить, присвоить) как в примере ниже:
function changeMaterial(el){//смена материала build
  var cloned = el.material.clone();
  cloned.emissive.setRGB(255, 100, 100); //например
  cloned.emissiveIntensity = 0.002; //степень наложения к примеру
  el.material = cloned; 
}
$('#changeMaterial').click(function(){
  //тут код зависит от того, в каком моменте вашего кода необходимо изменить
  //объект и каким способом вы получаете его (его имя),к примеру, мы знаем
  //имя объекта - 'home2'
  var el = scene.getObjectByName('home2')
  changeMaterial(el);
});
function addUnit(type, name){
  //как я говорил, для копирования юнитов со скелетной анимацией понадобится
  //модуль SkeletonUtils
  var unit = models[type][name].model.scene;
  var newunit = THREE.SkeletonUtils.clone(unit);
  // как подключать миксер анимаций - расписывать не буду, так как это уже
  //выходит за рамки вопроса и займет еще не мало строк кода и времени.
  scene.add(newunit);
}
</script>

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

→ Ссылка