Jetpack XR SDK מאפשר לכם להשתמש ב-Jetpack SceneCore כדי ליצור, לשלוט ולנהל מופעים של Entity
כמו מודלים תלת-ממדיים, סרטונים סטריאוסקופיים וPanelEntity
באמצעות Jetpack SceneCore.
ב-Jetpack SceneCore נעשה שימוש בשני דפוסי ארכיטקטורה נפוצים כדי לתמוך בפיתוח תלת-ממד: גרף סצנה ומערכת רכיבי ישויות (ECS).
שימוש בגרף הסצנה כדי ליצור ולשלוט בישויות
כדי ליצור אובייקטים במרחב תלת-ממדי ולשלוט בהם, אפשר להשתמש ב-Session API של Jetpack SceneCore כדי לקבל גישה לגרף הסצנה. גרף הסצנה מותאם לעולם האמיתי של המשתמש ומאפשר לארגן ישויות תלת-ממדיות כמו חלוניות ומודלים תלת-ממדיים במבנה היררכי, ולשמור את המצב של הישויות האלה.
אחרי שמקבלים גישה לגרף הסצנה, אפשר להשתמש בממשקי ה-API ב-Jetpack Compose for XR כדי ליצור ממשק משתמש מרחבי (לדוגמה, מופעים של SpatialPanel
ושל Orbiter
) בתוך גרף הסצנה. כדי לגשת לתוכן תלת-ממדי כמו מודלים תלת-ממדיים, אפשר להיכנס ישירות לסשן. מידע נוסף זמין בקטע מידע על ActivitySpace בדף הזה.
מערכת רכיבים של ישות
מערכת של ישויות ורכיבים פועלת לפי העיקרון של הרכבה על פני ירושה. אפשר להרחיב את ההתנהגות של ישויות על ידי צירוף רכיבים שמגדירים את ההתנהגות, וכך להחיל את אותה התנהגות על סוגים שונים של ישויות. מידע נוסף זמין במאמר בנושא הוספת התנהגות נפוצה לישויות בדף הזה.
מידע על ActivitySpace
לכל Session
יש ActivitySpace
שנוצר באופן אוטומטי עם Session
. ActivitySpace
הוא Entity
ברמה העליונה בתרשים של הסצנה.
המרחב ActivitySpace מייצג מרחב תלת-ממדי עם מערכת צירים ימנית (ציר ה-x מצביע ימינה, ציר ה-y מצביע למעלה וציר ה-z מצביע אחורה ביחס לנקודת המוצא) ועם יחידות של מטרים שתואמות לעולם האמיתי. המיקום של ActivitySpace
הוא שרירותי במידה מסוימת (כי המשתמשים יכולים לאפס את המיקום של ActivitySpace
בעולם האמיתי), ולכן מומלץ למקם את התוכן ביחס אחד לשני ולא ביחס למיקום של ActivitySpace
.
עבודה עם ישויות
הישויות הן מרכזיות ב-SceneCore. כמעט כל מה שהמשתמש רואה ומקיים איתו אינטראקציה הם ישויות שמייצגות חלוניות, מודלים תלת-ממדיים ועוד.
מכיוון ש-ActivitySpace
הוא הצומת ברמה העליונה בתרשים הסצנה, כברירת מחדל,
כל הישויות החדשות ממוקמות ישירות ב-ActivitySpace
. אפשר להעביר מיקומים של ישויות לאורך גרף הסצנה על ידי קריאה ל-setParent()
או ל-addChild()
.
לישויות יש כמה התנהגויות ברירת מחדל לגבי דברים שמשותפים לכל הישויות, כמו שינוי המיקום, הסיבוב או החשיפה. למחלקות משנה ספציפיות, כמו GltfModelEntity
, יש התנהגויות נוספות שתומכות במחלקת המשנה.Entity
שינוי ישויות
כשמבצעים שינוי בנכס 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
, משתמשים ב-setHidden()
.
// Hide the entity entity.setHidden(true)
כדי לשנות את הגודל של Entity
בלי לשנות את הצורה הכללית שלו, משתמשים ב-setScale()
.
// Double the size of the entity entity.setScale(2f)
הוספת התנהגות נפוצה לישויות
אפשר להשתמש ברכיבים הבאים כדי להוסיף התנהגות נפוצה לישויות:
-
MovableComponent
: מאפשר למשתמש להעביר ישויות -
ResizableComponent
: מאפשר למשתמש לשנות את הגודל של ישויות באמצעות דפוסי ממשק משתמש עקביים -
InteractableComponent
: מאפשרת לכם לתעד אירועי קלט לאינטראקציות מותאמות אישית
צריך ליצור מופעים של רכיבים באמצעות שיטת היצירה המתאימה במחלקה Session
. לדוגמה, כדי ליצור ResizableComponent
, קוראים ל-ResizableComponent.create()
.
כדי להוסיף את ההתנהגות הספציפית של הרכיב ל-Entity
, משתמשים בשיטה addComponent()
.
איך משתמשים ב-MovableComponent
כדי לאפשר למשתמשים להזיז ישות
ההרשאה MovableComponent
מאפשרת למשתמש להזיז את Entity
. אפשר גם לציין אם הישות יכולה להיות מוצמדת לסוג משטח כמו משטחים אופקיים או אנכיים, או למשטחים סמנטיים ספציפיים כמו שולחן, קיר או תקרה. כדי לציין אפשרויות של עוגן, מציינים קבוצה של AnchorPlacement
כשיוצרים את MovableComponent
.
דוגמה לישות שאפשר להזיז ולעגן לכל משטח אנכי, ורק למשטחים אופקיים של רצפה ותקרה.
val anchorPlacement = AnchorPlacement.createForPlanes( planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE), planeSemanticFilter = setOf(PlaneType.VERTICAL) ) val movableComponent = MovableComponent.create( session = session, systemMovable = false, scaleInZ = false, anchorPlacement = setOf(anchorPlacement) ) entity.addComponent(movableComponent)
כשהמשתמש מזיז את הישות, הפרמטר scaleInZ
משנה באופן אוטומטי את קנה המידה של הישות כשהיא מתרחקת מהמשתמש, בדומה לאופן שבו המערכת משנה את קנה המידה של החלוניות במרחב הביתי. בגלל האופי ההיררכי של מערכת רכיבי הישות, קנה המידה של רכיב האב ישפיע על כל רכיבי הצאצא שלו.
שימוש ב-ResizableComponent
כדי לשנות את הגודל של רכיב Entity
התכונה ResizableComponent
מאפשרת למשתמשים לשנות את הגודל של Entity
. האזור ResizableComponent
כולל רמזים חזותיים לאינטראקציה שמזמינים את המשתמש לשנות את הגודל של Entity
. כשיוצרים את ResizableComponent
, אפשר לציין גודל מינימלי או מקסימלי (במטרים). יש לכם גם אפשרות לציין יחס גובה-רוחב קבוע כשמשנים את הגודל, כך שהרוחב והגובה ישתנו באופן יחסי זה לזה.
כשמשתמשים ב-ResizableComponent
, צריך לציין ResizeListener
כדי להגיב לאירועי שינוי גודל ספציפיים, כמו onResizeUpdate
או onResizeEnd
.
דוגמה לשימוש בתג ResizableComponent
עם יחס רוחב-גובה קבוע בתג SurfaceEntity
:
val resizableComponent = ResizableComponent.create(session) resizableComponent.minimumSize = Dimensions(177f, 100f, 1f) resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio resizableComponent.addResizeListener( executor, object : ResizeListener { override fun onResizeEnd(entity: Entity, finalSize: Dimensions) { // update the size in the component resizableComponent.size = finalSize // update the Entity to reflect the new size (entity as SurfaceEntity).canvasShape = SurfaceEntity.CanvasShape.Quad(finalSize.width, finalSize.height) } }, ) entity.addComponent(resizableComponent)
שימוש ב-InteractableComponent
כדי לתעד אירועי קלט של משתמשים
התג InteractableComponent
מאפשר לכם לתעד אירועי קלט מהמשתמש, כמו כשמשתמש יוצר אינטראקציה עם Entity
או מעביר מעליו את העכבר. כשיוצרים InteractableComponent
, צריך לציין InputEventListener
כדי לקבל את אירועי הקלט. כשמשתמש מבצע פעולת קלט כלשהי, השיטה onInputEvent
נקראת עם פרטי הקלט הספציפיים שסופקו בפרמטר InputEvent
.
-
InputEvent.action
מציין את סוג הקלט, כמו העברת העכבר או הקשה על ישות -
InputEvent.source
מציין מאיפה הגיע הקלט, למשל קלט של יד או של בקר -
InputEvent.pointerType
מציין אם הקלט הגיע מיד ימין או מיד שמאל
רשימה מלאה של כל הקבועים של 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_TYPE_RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)