آشنایی با three-mesh-bvh: Three.js چطور مدل‌های سه‌بعدی عظیم را سریع‌تر مدیریت می‌کند

وقتی با سه‌بعدی در وب کار می‌کنید، خیلی زود به این مشکل می‌رسید: چطور با مدل‌های پیچیده سه‌بعدی تعامل کنیم بدون اینکه پرفورمنس از بین برود؟

یک نمایشگر ساده محصول ممکن است هزاران مثلث داشته باشد. یک مدل CAD، دوقلوی دیجیتال، محیط بازی یا صحنه معماری می‌تواند میلیون‌ها مثلث داشته باشد.

وقتی کاربر کلیک می‌کند، ماوس را حرکت می‌دهد، برخورد را بررسی می‌کند یا می‌پرسد «نزدیک‌ترین نقطه روی این سطح کجاست؟»، واقعاً باید تک‌تک مثلث‌ها را بررسی کنیم؟ جواب منفی است. اینجاست که BVH (سلسله‌مراتب حجم‌های محصورکننده) خیلی به کار می‌آید.

BVH چیست؟

BVH مخفف Bounding Volume Hierarchy است: یک ساختار شتاب‌دهنده فضایی که هندسه را در درختی از جعبه‌های محصورکننده سازمان‌دهی می‌کند. به جای بررسی مثلث‌ها یکی‌یکی، BVH یک سلسله‌مراتب می‌سازد:

               Model
                 |
       ---------------------
       |                   |
     Area A              Area B
       |                   |
   ---------           ---------
   |       |           |       |
Triangle Triangle  Triangle Triangle

حالا سیستم می‌تواند بخش‌های بزرگی از مدل را سریع نادیده بگیرد و فقط ناحیه‌ای را بررسی کند که مهم است.

پیدا کردن کتاب در کتابخانه را تصور کنید. بدون نظم، همه کتاب‌ها را می‌گردید. با نظم — بخش ← قفسه ← کتاب — خیلی سریع‌تر به نتیجه می‌رسید.

three-mesh-bvh چیست؟

three-mesh-bvh پیاده‌سازی BVH مخصوص مش‌های Three.js است و این کارها را بهبود می‌دهد:

  • Raycasting
  • تشخیص برخورد
  • پرس‌وجوهای فضایی
  • محاسبه نزدیک‌ترین نقطه
  • تست تقاطع هندسه‌ها

خود پروژه آن را این‌طور توصیف می‌کند: «پیاده‌سازی BVH برای سرعت دادن به Raycasting و امکان پرس‌وجوهای فضایی روی مش‌های three.js».

چرا Raycasting معمولی کند است؟

raycaster.intersectObject(mesh) خیلی کاربردی است، اما مش از مثلث‌ها ساخته شده. برای یک مدل پیچیده با ۵۰۰ هزار مثلث، اشعه مثلث ۱، مثلث ۲، مثلث ۳… تا مثلث ۵۰۰ هزارم را بررسی می‌کند.

برای آبجکت‌های کوچک مشکلی نیست. اما برای مدل‌های BIM، فایل‌های CAD، دوقلوهای دیجیتال و محیط‌های بزرگ پرهزینه می‌شود. BVH استراتژی جست‌وجو را عوض می‌کند.

یک مثال ساده در Three.js

بدون BVH:

const raycaster = new THREE.Raycaster();
const hits = raycaster.intersectObject(mesh);

با three-mesh-bvh:

import { MeshBVH, acceleratedRaycast } from "three-mesh-bvh";

geometry.boundsTree = new MeshBVH(geometry);
THREE.Mesh.prototype.raycast = acceleratedRaycast;

const raycaster = new THREE.Raycaster();
raycaster.firstHitOnly = true;

const hits = raycaster.intersectObject(mesh);

حالا اشعه کل هندسه را جست‌وجو نمی‌کند — از درخت BVH استفاده می‌کند و خیلی سریع‌تر به جواب می‌رسد.

یک تشبیه واقعی

وقتی در Google Maps «رستوران‌های نزدیک من» را جست‌وجو می‌کنید، همه رستوران‌های دنیا را بررسی نمی‌کند. از ایندکس‌های فضایی استفاده می‌کند: دنیا ← کشور ← شهر ← محله ← رستوران. BVH کار مشابهی برای هندسه سه‌بعدی انجام می‌دهد و به این سؤال‌ها جواب می‌دهد:

  • کدام بخش مدل زیر ماوس است؟
  • اشعه کجا برخورد کرد؟
  • نزدیک‌ترین سطح کدام است؟
  • آیا این آبجکت با آبجکت دیگری برخورد دارد؟

کاربردهای رایج در Three.js

۱. نمایشگرهای مدل‌های بزرگ

نمایشگرهای معماری، اپلیکیشن‌های BIM، نمایشگرهای CAD و دوقلوهای دیجیتال اغلب صدها هزار یا میلیون‌ها مثلث دارند. BVH تعامل را روان نگه می‌دارد.

۲. Raycasting پیشرفته

انتخاب آبجکت، افکت هاور، نقاشی روی سطح و ابزارهای اندازه‌گیری — پیدا کردن دقیق مثلثی که زیر ماوس است.

۳. تشخیص برخورد

بازی‌ها و شبیه‌سازی‌ها باید بپرسند «آیا کاراکتر به محیط برخورد کرده؟». به جای بررسی همه پلیگان‌ها، BVH جست‌وجو را سریع محدود می‌کند.

۴. فیزیک و شبیه‌سازی

BVH می‌تواند پرس‌وجوهای هندسی موتورهای فیزیک، پردازش هندسه و محاسبات فضایی را سریع‌تر کند.

۵. Path Tracing و رندر پیشرفته

BVH مفهومی پایه در Ray Tracing است. سیستم‌های رندر مدرن از ساختارهای شتاب‌دهنده استفاده می‌کنند چون شلیک اشعه به همه مثلث‌ها در مقیاس بزرگ غیرممکن است.

قابلیت‌های دیگر

این کتابخانه فقط برای Raycasting نیست: پرس‌وجوی نزدیک‌ترین نقطه، تقاطع با کره، تقاطع با جعبه، تقاطع هندسه‌ها و Shape Casting هم دارد.

const result = geometry.boundsTree.closestPointToPoint(point, target);

این کد جواب می‌دهد: «کدام نقطه روی این مش به موقعیت من نزدیک‌تر است؟»

مزایا

  • پرفورمنس: بهبود چشمگیر برای مش‌های پیچیده. صحنه‌ای که با Raycasting معمولی کند است می‌تواند تعاملی شود.
  • سازگاری با روند کاری فعلی: با Mesh، BufferGeometry و Raycaster یکپارچه می‌شود و نیازی به عوض کردن رندرر نیست.
  • امکان تعامل‌های پیشرفته: نقاشی سه‌بعدی، اندازه‌گیری CAD، ابزار ویرایش مش و سیستم‌های برخورد.

محدودیت‌ها

  • حافظه بیشتر: BVH ساختار داده اضافه می‌سازد. پرفورمنس بیشتر یعنی مصرف حافظه بیشتر.
  • زمان ساخت: ساختن درخت زمان می‌برد و برای مدل‌های خیلی بزرگ هزینه شروع دارد.
  • هندسه پویا سخت‌تر است: BVH برای هندسه ثابت بهترین است. اگر ورتکس‌ها در هر فریم تغییر کنند، BVH قدیمی می‌شود و باید دوباره ساخته یا Refit شود.

کی از three-mesh-bvh استفاده کنیم؟

وقتی اپلیکیشن شما مدل‌های سه‌بعدی بزرگ، Raycasting پیچیده، نمایشگر CAD/BIM، هندسه تعاملی، پرس‌وجوی فیزیک یا برخورد، یا تجربه‌های پیشرفته WebGL دارد. برای یک مکعب ساده چرخان احتمالاً لازم نیست؛ برای مدلی با یک میلیون مثلث تقریباً ضروری است.

جمع‌بندی

Three.js ساخت سه‌بعدی در وب را در دسترس کرده، اما چالش بعدی پرفورمنس است. three-mesh-bvh یک اصل مهم گرافیک کامپیوتری را نشان می‌دهد:

سریع‌ترین محاسبه، اغلب محاسبه‌ای است که انجامش نمی‌دهید.

به جای اینکه بپرسد «چطور مثلث‌های بیشتری پردازش کنیم؟»، BVH می‌پرسد «چطور به مثلث‌هایی که مهم نیستند نگاه نکنیم؟» — و این ایده یکی از پایه‌های اپلیکیشن‌های سه‌بعدی تعاملی مدرن است.

منابع: مثال Raycasting با BVH در three.js · three-mesh-bvh در npm