এনটিটি তৈরি, কন্ট্রোল ও ম্যানেজ করা

প্রযোজ্য XR ডিভাইস
এইসব XR ডিভাইসের জন্য অভিজ্ঞতা তৈরি করতে এই নির্দেশিকা আপনাকে সাহায্য করে।
XR হেডসেট
ওয়্যারড XR গ্লাস

Jetpack XR SDK আপনাকে Jetpack SceneCore ব্যবহার করে 3D মডেল, স্টেরিওস্কোপিক ভিডিও এবং PanelEntity-এর মতো Entity ইনস্ট্যান্স তৈরি, কন্ট্রোল ও ম্যানেজ করতে দেয়।

3D ডেভেলপমেন্টের জন্য Jetpack SceneCore দুটি সাধারণ আর্কিটেকচারাল প্যাটার্ন গ্রহণ করে: একটি সিন গ্রাফ এবং একটি এনটিটি-কম্পোনেন্ট সিস্টেম (ECS)।

এনটিটি তৈরি ও নিয়ন্ত্রণ করতে সিন গ্রাফ ব্যবহার করা

3D স্পেসে অবজেক্ট তৈরি ও কন্ট্রোল করতে, আপনি Jetpack SceneCore-এর Session API ব্যবহার করে সিন গ্রাফ অ্যাক্সেস করতে পারবেন। সিন গ্রাফ ব্যবহারকারীর বাস্তব জগতের সাথে সামঞ্জস্যপূর্ণ এবং এটি আপনাকে প্যানেল ও 3D মডেলের মতো 3D এন্টিটিগুলিকে একটি হায়ারার্কিক্যাল স্ট্রাকচারে সাজাতে এবং সেইসব এন্টিটির স্টেট হোল্ড করতে দেয়।

সিন গ্রাফে অ্যাক্সেস পাওয়ার পরে, আপনি Jetpack Compose for XR-এর API ব্যবহার করে সিন গ্রাফের মধ্যে স্পেশিয়াল UI (যেমন, SpatialPanel এবং Orbiter ইনস্ট্যান্স) তৈরি করতে পারবেন। 3D কন্টেন্টের ক্ষেত্রে, যেমন 3D মডেল, আপনি সরাসরি সেশন অ্যাক্সেস করতে পারবেন। আরও জানতে, এই পৃষ্ঠায় ActivitySpace সম্পর্কে জানুন।

এন্টিটি কম্পোনেন্ট সিস্টেম

একটি এন্টিটি কম্পোনেন্ট সিস্টেম ইনহেরিটেন্সের পরিবর্তে কম্পোজিশনের নীতি অনুসরণ করে। আপনি আচরণ-সংজ্ঞায়িত কম্পোনেন্ট অ্যাটাচ করে এন্টিটির আচরণকে আরও বিস্তারিত করতে পারেন, যা আপনাকে বিভিন্ন ধরনের এন্টিটিতে একই আচরণ প্রয়োগ করতে দেয়। আরও তথ্যের জন্য, এই পৃষ্ঠায় এনটিটিতে সাধারণ ব্যবহার যোগ করুন বিকল্প দেখুন।

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-এর মাধ্যমে 3D স্পেসের মধ্যে Entity-র লোকেশন ও রোটেশন বোঝানো হয়। লোকেশন হল একটি 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: ব্যবহারকারীকে সামঞ্জস্যপূর্ণ UI প্যাটার্ন সহ এন্টিটির সাইজ পরিবর্তন করতে দেয়
  • InteractableComponent: কাস্টম ইন্টার‍্যাকশনের জন্য ইনপুট ইভেন্ট ক্যাপচার করতে দেয়

Session ক্লাসে উপযুক্ত ক্রিয়েশন পদ্ধতির মাধ্যমে কম্পোনেন্ট ইনস্ট্যানশিয়েট করতে হবে। যেমন, ResizableComponent তৈরি করতে, কল করুন ResizableComponent.create()।

Entity-এ নির্দিষ্ট কম্পোনেন্ট আচরণ যোগ করতে, addComponent() পদ্ধতি ব্যবহার করুন।

কোনও এন্টিটি ব্যবহারকারী-মুভেবল করতে MovableComponent ব্যবহার করুন

MovableComponent ব্যবহারকারীকে Entity সরানোর অনুমতি দেয়।

সাজসজ্জার সাথে ইন্টার‍্যাক্ট করা হলে, কম্পোনেন্টে মুভমেন্ট ইভেন্ট ডিসপ্যাচ করা হয়। MovableComponent.createSystemMovable()-এর মাধ্যমে তৈরি করা ডিফল্ট সিস্টেম আচরণ, আপনার Entity সরিয়ে দেয় যখন সাজসজ্জা টেনে আনা হয়:

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

ঐচ্ছিক scaleInZ প্যারামিটার (সাধারণত true হিসেবে সেট করা থাকে), Entity-কে ব্যবহারকারীর থেকে দূরে সরানোর সাথে সাথে অটোমেটিক এর স্কেল অ্যাডজাস্ট করে, ঠিক যেভাবে হোম স্পেসে সিস্টেমের মাধ্যমে প্যানেল স্কেল করা হয়। এনটিটি কম্পোনেন্ট সিস্টেমের "ক্যাসকেডিং" প্রকৃতির কারণে, পেরেন্টের স্কেল এর সমস্ত চাইল্ডকে প্রভাবিত করবে।

এছাড়াও, আপনি নির্দিষ্ট করতে পারবেন যে এন্টিটিটি অনুভূমিক বা উল্লম্ব সারফেসের মতো কোনও সারফেসের সাথে অ্যাঙ্কর করা যাবে কিনা অথবা টেবিল, দেওয়াল বা ছাদের মতো নির্দিষ্ট সিম্যান্টিক সারফেসের সাথে অ্যাঙ্কর করা যাবে কিনা। অ্যাঙ্কর বিকল্প নির্দিষ্ট করতে, 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)

রানটাইমে কাস্টম 3D মডেল তৈরি করা

Custom Mesh API আপনাকে glTF ফাইলের মতো স্ট্যাটিক অ্যাসেট লোড করার পরিবর্তে সরাসরি আপনার কোডে প্রোগ্র্যামাটিক উপায়ে 3D শেপ তৈরি করতে দেয়। আপনি ফ্লাইটে কাস্টম জ্যামিতি তৈরি করে, প্রসিডিওরাল ডেটা, ডায়নামিক কাস্টম শেপ এবং অসীম 3D এনভায়রনমেন্ট রেন্ডার করতে পারেন, যেমন, আপনার ব্যবহারকারীরা এক্সপ্লোর করার সাথে সাথে ক্রমাগত তৈরি হতে থাকা ভূখণ্ড। এছাড়াও, রানটাইমে মেশ তৈরি করার ফলে, একটি 3D অ্যাসেটের অসংখ্য ভেরিয়েন্ট প্যাকেজ করার প্রয়োজনীয়তা দূর করে ছোট বাইনারি সাইজ তৈরি করতে সাহায্য করে।