Если вы уже посещали мой личный сайт, то, возможно, вы нашли эту (несколько) скрытую модель лего.

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

В то время мне было интересно поиграть с 3D-моделями в JavaScript, и я знал о популярной библиотеке ThreeJS мистера Дуба.

Но у меня не было (до сих пор есть и, вероятно, будет…) опыта работы с программами для моделирования, такими как Blender.

Но я знаю свой Лего!

Студия БрикЛинк

BrickLink, популярная торговая площадка Lego, управляемая сообществом (которая, что забавно, теперь принадлежит Lego), имеет инструмент для создания цифровых моделей Lego под названием Studio.

После загрузки инструмента вы обнаружите, что им относительно просто пользоваться. Если вы хорошо разбираетесь в деталях лего, вы можете найти подходящие кубики, которые вам нужны, чтобы построить все, что вы хотите. Вы даже можете импортировать настоящие наборы Lego! Но многие наборы, такие как наборы со специальными деталями, цветами или наклейками, скорее всего, не смогут импортировать все необходимые детали. Я нашел линейку BrickHeadz по большей части успешной.

Ладно, отвлеклись — дело в том, что это самый простой способ оцифровать ваши творения Lego!

Вот неэффективная замедленная съемка моего создания логотипа Lego Batman! Вы можете видеть, как я борюсь, но в конце концов я получил то, что хотел :)

Введите триJS

После того, как вы закончите создание своей модели, обязательно экспортируйте ее как файл Ldraw ( File -> Export As -> Export As LDraw...).

  1. Теперь создайте стандартный HTML-файл следующим образом:
  2. Создайте файл model.js в том же каталоге этого проекта, в котором эта страница запускается при загрузке. Примечание. Как и в приведенном выше HTML-шаблоне, убедитесь, что тег <script> имеет тип module (ThreeJS требует, чтобы этот файл был модулем ES).
  3. Установить ThreeJS

Упаковка модели LDraw

LDrawLoader ThreeJS — это то, что мы используем для загрузки нашей модели, но по умолчанию он фактически загружает упакованные модели LDraw. Это означает, что он не поддерживает извлечение одной модели LDraw.

К счастью, в документах ThreeJS есть раздел Упаковка моделей Ldraw, где вы загружаете последнюю библиотеку деталей LDraw и запускаете этот официальный скрипт на вашей модели LDraw, которую вы экспортировали из Studio.

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

Импорт модели LDraw

Следующий код JavaScript ( model.js) использует этот учебник по ThreeJS GLTFLoader в качестве шаблона. Основные изменения — это изменение загрузчика на LDrawLoader и добавление точки поворота, чтобы мы могли вращаться вокруг центра объекта, а не вокруг центра мира (проблема, с которой я столкнулся и которую решил благодаря этому SO-сообщению).

import * as THREE from "three";
// orbit controls so you can drag and play around with the model in space
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// import the loader
import { LDrawLoader } from "three/examples/jsm/loaders/LDrawLoader";
// import the packed model
import batman from "./batman.ldr_Packed.mpd";
// performance stats that you can see on the top left corner
import Stats from "three/examples/jsm/libs/stats.module";
// need to create a scene to add the model first
const scene = new THREE.Scene();
scene.add(new THREE.AxesHelper(5));
// adding a light source (used to highlight a specific part of the model)
const light = new THREE.PointLight();
// position depends on how your model loads
light.position.set(0.8, 1.4, 1.0);
scene.add(light);
// adding another light source but this one lights the entire scene
const ambientLight = new THREE.AmbientLight("yellow");
scene.add(ambientLight);
// create the view
const camera = new THREE.PerspectiveCamera(
  100,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
// position depends on how and where the model loads
// might need to tinker with these values
camera.position.set(0, 50, 400);
// adding the render space
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// adding the orbit controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.target.set(0, 1, 0);
// initializing the loader
const loader = new LDrawLoader();
let loadedModel;
// create a pivot to rotate the on model
let pivot = new THREE.Group();
scene.add(pivot);
// load the model
loader.load(
  batman,
  (object) => {
    loadedModel = object;
    pivot.add(object);
  },
  (xhr) => {
    console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
  },
  (error) => {
    console.log(error);
  }
);
// resize window settings
window.addEventListener("resize", onWindowResize, false);
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  render();
}
// only rotate the model on double click
let rotateModel = false;
window.addEventListener("dblclick", () => (rotateModel = !rotateModel));
// add the stats
const stats = Stats();
document.body.appendChild(stats.dom);
// animate the model (this acts as an event loop)
// only after the model has loaded (and the user double clicks)
// will the model be able to animate
function animate() {
  requestAnimationFrame(animate);
if (loadedModel && rotateModel) {
    pivot.rotation.y += 0.02;
  }
  controls.update();
render();
stats.update();
}
function render() {
  renderer.render(scene, camera);
}
animate();

Первоначально опубликовано наhttps://blog.kperath.com/posts/lego-model-with-threejs/