ایجاد، کنترل، و مدیریت نهادها

دستگاه‌های XR قابل‌اعمال
این راهنمایی به شما کمک می‌کند برای این نوع دستگاه‌های واقعیت گسترده تجربه بسازید.
هدست‌های واقعیت گسترده
عینک واقعیت گسترده سیمی

«کیت توسعه نرم‌افزار Jetpack XR» به شما امکان می‌دهد بااستفاده از Jetpack SceneCore، نمونه‌هایی Entity مثل مدل‌های سه‌بعدی، ویدیوهای استریوسکوپی، و PanelEntity را ایجاد، کنترل، و مدیریت کنید.

‫Jetpack SceneCore از دو الگوی معماری رایج برای پشتیبانی از توسعه سه‌بعدی استفاده می‌کند: گراف صحنه و سیستم نهاد-جزء (ECS).

از گراف صحنه برای ایجاد و کنترل نهادها استفاده کنید

برای ایجاد و کنترل کردن اشیا در فضای سه‌بعدی، می‌توانید از Session API در Jetpack SceneCore برای دسترسی به گراف صحنه استفاده کنید. گراف صحنه با دنیای واقعی کاربر هم‌تراز می‌شود و به شما امکان می‌دهد نهادهای سه‌بعدی مثل پانل‌ها و مدل‌های سه‌بعدی را در ساختاری سلسله‌مراتبی سازمان‌دهی کنید و وضعیت این نهادها را حفظ کنید.

پس‌از دسترسی به گراف صحنه، می‌توانید از «میاناهای برنامه‌سازی کاربردی» در Jetpack Compose for XR برای ایجاد میانای کاربری فضایی (برای مثال، SpatialPanel و Orbiter نمونه‌ها) در گراف صحنه استفاده کنید. برای محتوای سه‌بعدی مثل مدل‌های سه‌بعدی، می‌توانید مستقیماً به «جلسه» دسترسی داشته باشید. برای کسب اطلاعات بیشتر، در این صفحه درباره فضای فعالیت را ببینید.

سیستم مؤلفه نهاد

سیستم مؤلفه نهاد از اصل ترکیب بر وراثت پیروی می‌کند. با پیوست کردن عناصر تعریف‌کننده رفتار می‌توانید رفتار نهادها را گسترش دهید، که به شما امکان می‌دهد رفتار یکسانی را برای انواع مختلف نهادها اعمال کنید. برای اطلاعات بیشتر، افزودن رفتار مشترک به نهادها را در این صفحه بررسی کنید.

درباره ActivitySpace

هر Session یک ActivitySpace دارد که به‌طور خودکار با Session ایجاد می‌شود. ActivitySpace بالاترین سطح Entity در گراف صحنه است.

‫ActivitySpace فضایی سه‌بعدی با سیستم مختصات راست‌دست (محور x به راست، محور y به بالا، و محور z به عقب نسبت به مبدأ) و با واحدهای متر که با دنیای واقعی مطابقت دارد را نشان می‌دهد. مبدأ ActivitySpace تا حدودی اختیاری است (زیرا کاربران می‌توانند موقعیت ActivitySpace را در دنیای واقعی بازنشانی کنند)، بنابراین توصیه می‌شود محتوا را نسبت‌به یکدیگر قرار دهید نه نسبت‌به مبدأ.

کار کردن با نهادها

نهادها در SceneCore مرکزی هستند. تقریباً هر چیزی که کاربر می‌بیند و با آن تعامل می‌کند نهادهایی هستند که پانل‌ها، مدل‌های سه‌بعدی، و غیره را نشان می‌دهند.

ازآنجایی‌که ActivitySpace گره سطح بالای گراف صحنه است، به‌طور پیش‌فرض، همه نهادهای جدید مستقیماً در ActivitySpace قرار می‌گیرند. با تنظیم parent یا بااستفاده از addChild() می‌توانید جای موجودیت‌ها را در امتداد گراف صحنه تغییر دهید.

نهادها برای چیزهایی که برای همه نهادها جهانی است، مثل تغییر موقعیت، چرخش، یا رؤیت‌پذیری، رفتارهای پیش‌فرضی دارند. زیرکلاس‌های خاص Entity مثل GltfModelEntity، رفتارهای اضافه‌ای دارند که از زیرکلاس پشتیبانی می‌کنند.

دستکاری نهادها

وقتی تغییری در دارایی Entity ایجاد می‌کنید که متعلق به کلاس پایه Entity است، این تغییر به همه فرزندان آن سرایت می‌کند. برای مثال، تغییر Pose یک والد Entity منجر به این می‌شود که همه فرزندانش همان تغییر را داشته باشند. ایجاد تغییر در Entity فرزند تأثیری بر ولی او ندارد.

Pose موقعیت و چرخش «نهاد» را در فضای سه‌بعدی نشان می‌دهد. مکان یک Vector3 متشکل از موقعیت‌های عددی x،‏ y،‏ z است. چرخش با Quaternion نشان داده می‌شود. موقعیت Entity همیشه نسبت به نهاد مادر آن است. به‌عبارت دیگر، Entity که موقعیت آن ‏ (۰، ۰، ۰) باشد در مبدأ نهاد والد خود قرار می‌گیرد.

// Place the entity forward 2 meters
val newPosition = Vector3(0f, 0f, -2f)
// Rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
// Update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))

برای غیرفعال کردن Entity، از setEnabled() استفاده کنید. این کار باعث می‌شود نامرئی شود و همه پردازش‌های انجام‌شده روی آن متوقف می‌شود.

// Disable the entity.
entity.setEnabled(false)

برای تغییر اندازه Entity ضمن حفظ شکل کلی آن، از setScale() استفاده کنید.

// Double the size of the entity
entity.setScale(2f)

افزودن رفتار مشترک به نهادها

می‌توانید از عناصر زیر برای افزودن رفتار مشترک به نهادها استفاده کنید:

  • MovableComponent: به کاربر اجازه می‌دهد نهادها را حرکت دهد
  • ResizableComponent: به کاربر اجازه می‌دهد تا اندازه نهادها را با الگوهای میانای کاربر یکسان تغییر دهد
  • InteractableComponent: به شما امکان می‌دهد رویدادهای ورودی را برای تعاملات سفارشی ضبط کنید

ایجاد نمونه از عناصر باید ازطریق روش ایجاد مناسب در کلاس Session انجام شود. برای مثال، برای ایجاد ResizableComponent، با ResizableComponent.create() تماس بگیرید.

برای افزودن رفتار عنصر خاص به Entity، از روش addComponent() استفاده کنید.

از MovableComponent برای تبدیل «نهاد» به «کاربر-جابه‌جاشدنی» استفاده کنید

MovableComponent به Entity اجازه می‌دهد توسط کاربر جابه‌جا شود.

وقتی با تزیینات تعامل برقرار می‌شود، رویدادهای حرکت به عنصر ارسال می‌شود. رفتار پیش‌فرض سیستم، ایجادشده با MovableComponent.createSystemMovable()، Entity شما را هنگام کشیدن تزئینات حرکت می‌دهد:

val movableComponent = MovableComponent.createSystemMovable(session)
entity.addComponent(movableComponent)

پارامتر اختیاری scaleInZ (به‌طور پیش‌فرض روی true تنظیم شده است)، باعث می‌شود «نهاد» به‌طور خودکار مقیاس خود را با دور شدن از کاربر تنظیم کند، به‌شیوه‌ای مشابه با نحوه مقیاس‌بندی پانل‌ها توسط سیستم در فضای خانه. به‌دلیل ماهیت «آبشاری» سیستم مؤلفه نهاد، مقیاس والد بر همه فرزندانش تأثیر خواهد گذاشت.

همچنین می‌توانید مشخص کنید که آیا نهاد می‌تواند به نوع سطحی مانند سطوح افقی یا عمودی، یا سطوح معنایی خاص مانند میز، دیوار، یا سقف متصل شود یا نه. برای مشخص کردن گزینه‌های لنگر، هنگام ایجاد MovableComponent، مجموعه‌ای از AnchorPlacement را مشخص کنید. در این مثال، نهادی که می‌تواند به هر سطح افقی میز یا کف منتقل و لنگر شود:

val anchorPlacement = AnchorPlacement.createForPlanes(
    anchorablePlaneOrientations = setOf(PlaneOrientation.VERTICAL),
    anchorablePlaneSemanticTypes = setOf(PlaneSemanticType.FLOOR, PlaneSemanticType.TABLE)
)

val movableComponent = MovableComponent.createAnchorable(
    session = session,
    anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)

از ResizableComponent برای تغییر اندازه «کاربر نهاد» استفاده کنید

ResizableComponent به کاربران اجازه می‌دهد اندازه Entity را تغییر دهند. ResizableComponent شامل نشانه‌های تعامل بصری است که کاربر را به تغییر اندازه Entity دعوت می‌کند. هنگام ایجاد ResizableComponent، می‌توانید اندازه حداقل یا حداکثر (برحسب متر) را مشخص کنید. همچنین می‌توانید نسبت ابعادی ثابتی را هنگام تغییر اندازه مشخص کنید تا عرض و ارتفاع به‌صورت متناسب با یکدیگر تغییر اندازه دهند.

هنگام ایجاد ResizableComponent، resizeEventListener را مشخص کنید که رویدادهای به‌روزرسانی را مدیریت می‌کند. می‌توانید به ResizeState رویدادهای مختلف، مثل RESIZE_STATE_ONGOING یا RESIZE_STATE_END، پاسخ دهید.

در اینجا نمونه‌ای از استفاده از ResizableComponent با نسبت ابعادی ثابت در SurfaceEntity آورده شده است:

val resizableComponent = ResizableComponent.create(session) { event ->
    if (event.resizeState == ResizeEvent.ResizeState.END) {
        // update the Entity to reflect the new size
        surfaceEntity.shape = SurfaceEntity.Shape.Quad(FloatSize2d(event.newSize.width, event.newSize.height))
    }
}
resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f)
resizableComponent.isFixedAspectRatioEnabled = true // Maintain a fixed aspect ratio when resizing

surfaceEntity.addComponent(resizableComponent)

از InteractableComponent برای ضبط رویدادهای ورودی کاربر استفاده کنید

InteractableComponent به شما امکان می‌دهد رویدادهای ورودی را از کاربر دریافت کنید، مثلاً زمانی که کاربر با Entity تعامل می‌کند یا روی آن نگه می‌دارد. هنگام ایجاد InteractableComponent، شنونده‌ای را مشخص کنید که رویدادهای ورودی را دریافت می‌کند. وقتی کاربر کنش ورودی انجام می‌دهد، شنونده با اطلاعات ورودی ارائه‌شده در پارامتر InputEvent فراخوانده می‌شود.

برای فهرست کامل همه ثابت‌های InputEvent، مستندات مرجع را ببینید.

تکه کد زیر نمونه‌ای از استفاده از InteractableComponent برای افزایش اندازه یک نهاد با دست راست و کاهش آن با دست چپ را نشان می‌دهد.

val executor = Executors.newSingleThreadExecutor()
val interactableComponent = InteractableComponent.create(session, executor) {
    // when the user disengages with the entity with their hands
    if (it.source == InputEvent.Source.HANDS && it.action == InputEvent.Action.UP) {
        // increase size with right hand and decrease with left
        if (it.pointerType == InputEvent.Pointer.RIGHT) {
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.Pointer.LEFT) {
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)

ایجاد مدل‌های سه‌بعدی سفارشی در زمان اجرا

«میانای برنامه‌سازی کاربردی مش سفارشی» به شما امکان می‌دهد شکل‌های سه‌بعدی را به‌صورت برنامه‌ریزی‌شده مستقیماً در کدتان تولید کنید، به‌جای اینکه دارایی‌های ایستا مثل فایل‌های glTF را بار کنید. با ساختن هندسه سفارشی در لحظه، می‌توانید داده‌های رویه‌ای، شکل‌های سفارشی پویا، و محیط‌های سه‌بعدی به‌ظاهر بی‌نهایت مثل عوارض زمین را که با کاوش کاربران به‌طور پیوسته تولید می‌شود پرداز کنید. علاوه‌براین، تولید کردن مش‌ها در زمان اجرا با ازبین بردن نیاز به بسته‌بندی کردن تنوع بی‌شمار یک دارایی سه‌بعدی واحد، به کوچک‌تر شدن اندازه‌های باینری کمک می‌کند.