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

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

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

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

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

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

سیستم اجزای نهاد

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

درباره ActivitySpace

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

ActivitySpace یک فضای 3 بعدی را با یک سیستم مختصات سمت راست نشان می دهد (محور 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 که موقعیت آن (0، 0، 0) است در مبدأ موجودیت اصلی خود قرار می گیرد.

// 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 برای تبدیل شدن یک Entity به کاربر استفاده کنید

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

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

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

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

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

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 برای ایجاد یک Entity قابل تغییر اندازه توسط کاربر استفاده کنید

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.RESIZE_STATE_END) {
        // update the Entity to reflect the new size
        surfaceEntity.canvasShape = SurfaceEntity.CanvasShape.Quad(event.newSize.width, event.newSize.height)
    }
}
resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f)
resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio

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.SOURCE_HANDS && it.action == InputEvent.Action.ACTION_UP) {
        // increase size with right hand and decrease with left
        if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_RIGHT) {
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_LEFT) {
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)