ส่วนขยาย XR_ANDROID_hand_mesh ของ OpenXR

สตริงชื่อ

XR_ANDROID_hand_mesh

ประเภทชิ้นงาน

การขยายเวลาอินสแตนซ์

หมายเลขต่อที่จดทะเบียน

704

การแก้ไข

1

การพึ่งพาส่วนขยายและเวอร์ชัน

OpenXR 1.0

วันที่แก้ไขล่าสุด

2024-09-10

สถานะ IP

ไม่มีการอ้างสิทธิ์ IP ที่รู้จัก

ผู้เขียน

Nihav Jain จาก Google

Cairn Overturf จาก Google

Spencer Quin จาก Google

Levana Chen จาก Google

ภาพรวม

ส่วนขยายนี้เปิดใช้การติดตามการเคลื่อนไหวของมือที่แสดงเป็นตาข่ายมือแบบไดนามิก

ส่วนขยายนี้มีไว้เพื่อจัดเตรียมบัฟเฟอร์เวิร์กเท็กซ์และอินเด็กซ์สำหรับเมชของการแสดงภาพมือของผู้ใช้ที่ปรับเปลี่ยนในแบบของคุณ ใช้ได้กับการบดบังและการแสดงภาพ

ไม่ควรใช้ส่วนขยายนี้เพื่อวัตถุประสงค์ในการติดตามมืออื่นๆ

ข้อมูลการติดตามมืออาจเป็นข้อมูลส่วนบุคคลที่มีความละเอียดอ่อนและเชื่อมโยงกับความเป็นส่วนตัวและความเป็นธรรมส่วนบุคคลอย่างใกล้ชิด เราขอแนะนำอย่างยิ่งว่าแอปพลิเคชันที่จัดเก็บหรือโอนข้อมูลการติดตามมือควรขอความยินยอมจากผู้ใช้อย่างชัดเจนและใช้งานได้เสมอ

ตรวจสอบความสามารถของระบบ

แอปพลิเคชันสามารถตรวจสอบว่าระบบสามารถติดตามเมชของมือได้หรือไม่โดยเชื่อมโยงโครงสร้าง XrSystemHandMeshTrackingPropertiesANDROID กับ XrSystemProperties เมื่อเรียกใช้ xrGetSystemProperties

typedef struct XrSystemHandMeshTrackingPropertiesANDROID {
  XrStructureType    type;
  void*              next;
  XrBool32           supportsHandMeshTracking;
  XrBool32           supportsTextureUV;
  XrBool32           supportsVertexNormal;
} XrSystemHandMeshTrackingPropertiesANDROID;

คำอธิบายสมาชิก

  • type คือ XrStructureType ของโครงสร้างนี้
  • next คือ NULL หรือพอยน์เตอร์ไปยังโครงสร้างถัดไปในเชนโครงสร้าง ไม่มีการกำหนดโครงสร้างดังกล่าวใน OpenXR หลักหรือส่วนขยายนี้
  • supportsHandMeshTracking คือ XrBool32 ซึ่งระบุว่า XrSystemId ที่เลือกรองรับการติดตามเมชมือหรือไม่
  • supportsTextureUV คือ XrBool32 ซึ่งระบุว่า XrSystemId ที่เลือกรองรับ UV ของพื้นผิวสำหรับจุดยอดของเมชหรือไม่
  • supportsVertexNormal คือ XrBool32 ซึ่งระบุว่า XrSystemId ที่เลือกรองรับเวิร์กเซลเวิร์กเซลของเมชหรือไม่

แอปพลิเคชันควรหลีกเลี่ยงการใช้ความสามารถของเมชมือเมื่อ supportsHandMeshTracking เป็น XR_FALSE เนื่องจากหมายความว่าระบบไม่รองรับการติดตามเมชมือ ในกรณีนี้ xrCreateHandMeshTrackerANDROID จะแสดงผล XR_ERROR_FEATURE_UNSUPPORTED

หาก supportsHandMeshTracking แสดงผลเป็น XR_TRUE แสดงว่าระบบรองรับการติดตามเมชมือ แอปพลิเคชันควรใช้ XrHandMeshANDROID::indexCount และ XrHandMeshANDROID::vertexCount เพื่อเข้าถึงบัฟเฟอร์เมชมือและนำกลับมาใช้ใหม่ในลูปเรนเดอร์เมื่อเรียกใช้ xrGetHandMeshANDROID ทุกเฟรม

หาก supportsTextureUV แสดงผลเป็น XR_FALSE แสดงว่าระบบไม่รองรับ UV ของพื้นผิวสำหรับจุดยอดของเมช ดังนั้นแอปพลิเคชันจะได้รับ XrHandMeshANDROID::textureUVs NULL เมื่อเรียกใช้ xrGetHandMeshANDROID

หาก supportsVertexNormal แสดงผลเป็น XR_FALSE แสดงว่าระบบไม่รองรับเวิร์กเซลเวิร์กเทกซ์สำหรับเวิร์กเทกซ์ของเมช ดังนั้นแอปพลิเคชันจะได้รับ XrHandMeshANDROID::normals NULL เมื่อเรียกใช้ xrGetHandMeshANDROID

การใช้งานที่ถูกต้อง (โดยนัย)

สร้างแฮนเดิลอุปกรณ์ติดตามแบบตาข่ายสำหรับมือ

XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)

แฮนเดิล XrHandMeshTrackerANDROID แสดงถึงอุปกรณ์ติดตามเมชมือสำหรับการติดตามเมชมือและจัดการทรัพยากรที่เกี่ยวข้อง

แฮนเดิลนี้สามารถใช้เพื่อเข้าถึงบัฟเฟอร์เมชมือโดยใช้ฟังก์ชันอื่นๆ ในส่วนขยายนี้ได้

แอปพลิเคชันสามารถสร้างแฮนเดิล XrHandMeshTrackerANDROID โดยใช้ฟังก์ชัน xrCreateHandMeshTrackerANDROID

XrResult xrCreateHandMeshTrackerANDROID(
    XrSession                                   session,
    const XrHandMeshTrackerCreateInfoANDROID*   createInfo,
    XrHandMeshTrackerANDROID*                   handMeshTracker);

คําอธิบายพารามิเตอร์

  • session คือ XrSession ที่อุปกรณ์ติดตามแบบตาข่ายที่มือจะทำงานอยู่
  • createInfo คือ XrHandMeshTrackerCreateInfoANDROID ที่ใช้ในการระบุเครื่องมือติดตามเมชมือ
  • handMeshTracker คือแฮนเดิล XrHandMeshTrackerANDROID ที่แสดงผล

หากระบบไม่รองรับการติดตามเมชมือ xrCreateHandMeshTrackerANDROID จะแสดงผลเป็น XR_ERROR_FEATURE_UNSUPPORTED

แฮนเดิล XrHandMeshTrackerANDROID เป็นเจ้าของทรัพยากรทั้งหมดสำหรับการติดตามเมชมือ หลังจากใช้งานการติดตามเมชมือเสร็จแล้ว แอปพลิเคชันต้องทำลายตัวแฮนเดิลโดยใช้ฟังก์ชัน xrDestroyHandMeshTrackerANDROID

การใช้งานที่ถูกต้อง (โดยนัย)

  • ต้องเปิดใช้ส่วนขยาย XR_ANDROID_hand_mesh ก่อนเรียกใช้ xrCreateHandMeshTrackerANDROID
  • session ต้องเป็นแฮนเดิล XrSession ที่ถูกต้อง
  • createInfo ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrHandMeshTrackerCreateInfoANDROID ที่ถูกต้อง
  • handMeshTracker ต้องเป็นพอยน์เตอร์ไปยังตัวแฮนเดิล XrHandMeshTrackerANDROID

รหัสการคืนสินค้า

สำเร็จ

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

ไม่สำเร็จ

  • XR_ERROR_FEATURE_UNSUPPORTED
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_LIMIT_REACHED

โครงสร้าง XrHandMeshTrackerCreateInfoANDROID อธิบายข้อมูลในการสร้างแฮนเดิล XrHandMeshTrackerANDROID

typedef struct XrHandMeshTrackerCreateInfoANDROID {
    XrStructureType    type;
    const void*        next;
} XrHandMeshTrackerCreateInfoANDROID;

คำอธิบายสมาชิก

  • type คือ XrStructureType ของโครงสร้างนี้
  • next คือ NULL หรือพอยน์เตอร์ไปยังโครงสร้างถัดไปในเชนโครงสร้าง ไม่มีการกำหนดโครงสร้างดังกล่าวใน OpenXR หลักหรือส่วนขยายนี้

การใช้งานที่ถูกต้อง (โดยนัย)

ฟังก์ชัน xrDestroyHandMeshTrackerANDROID จะปล่อยhandMeshTracker และทรัพยากรที่เกี่ยวข้องเมื่อประสบการณ์การติดตามเมชมือสิ้นสุดลง

XrResult xrDestroyHandMeshTrackerANDROID(
    XrHandMeshTrackerANDROID handMeshTracker);

คําอธิบายพารามิเตอร์

การใช้งานที่ถูกต้อง (โดยนัย)

ความปลอดภัยของชุดข้อความ

  • การเข้าถึง handMeshTracker และตัวแฮนเดิลย่อยต้องได้รับการซิงค์จากภายนอก

รหัสการคืนสินค้า

สำเร็จ

  • XR_SUCCESS

ไม่สำเร็จ

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID

ค้นหาเมชมือ

แอปพลิเคชันสามารถใช้ฟังก์ชัน xrGetHandMeshANDROID เพื่อดึงข้อมูลเมชมือ ณ การประทับเวลาหนึ่งๆ ตำแหน่งและเวิร์กเทอร์มินัลของเมชมือจะแสดงในพื้นที่ที่ระบุโดย XrHandMeshGetInfoANDROID::baseSpace เมื่อเรียกใช้ xrGetHandMeshANDROID

XrResult xrGetHandMeshANDROID(
    XrHandMeshTrackerANDROID                    handMeshTracker,
    const XrHandMeshGetInfoANDROID*             getInfo,
    XrHandTrackingMeshesANDROID*                handMeshes);

คําอธิบายพารามิเตอร์

  • handMeshTracker คือแฮนเดิล XrHandMeshTrackerANDROID ที่สร้างไว้ก่อนหน้านี้ด้วย xrCreateHandMeshTrackerANDROID
  • getInfo คือโครงสร้าง XrHandMeshGetInfoANDROID ซึ่งมีข้อมูลสําหรับค้นหาข้อมูลเมชมือ
  • handMeshes คือพอยน์เตอร์ไปยังโครงสร้าง XrHandTrackingMeshesANDROID ซึ่งจะป้อนข้อมูลเมชมือ

แอปพลิเคชันสามารถใช้ฟังก์ชัน xrGetHandMeshANDROID เพื่อเข้าถึงบัฟเฟอร์เมชมือที่รันไทม์สร้างขึ้น

แอปพลิเคชันควรเรียกใช้ xrBeginFrame อย่างน้อย 1 ครั้งในระหว่างเซสชันก่อนการเรียกใช้ xrGetHandMeshANDROID ครั้งแรก

แอปพลิเคชันควรใช้ XrHandMeshANDROID::indexCount และ XrHandMeshANDROID::vertexCount เพื่อเข้าถึงบัฟเฟอร์เมชมือและนํากลับมาใช้ใหม่ในลูปเรนเดอร์เมื่อเรียกใช้ xrGetHandMeshANDROID ทุกเฟรม

การใช้งานที่ถูกต้อง (โดยนัย)

  • ต้องเปิดใช้ส่วนขยาย XR_ANDROID_hand_mesh ก่อนเรียกใช้ xrGetHandMeshANDROID
  • handMeshTracker ต้องเป็นแฮนเดิล XrHandMeshTrackerANDROID ที่ถูกต้อง
  • getInfo ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrHandMeshGetInfoANDROID ที่ถูกต้อง
  • handMeshes ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrHandTrackingMeshesANDROID

รหัสการคืนสินค้า

สำเร็จ

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

ไม่สำเร็จ

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_SIZE_INSUFFICIENT
  • XR_ERROR_TIME_INVALID

XrHandMeshGetInfoANDROID อธิบายข้อมูลที่จำเป็นในการรับข้อมูลเมชมือ

typedef struct XrHandMeshGetInfoANDROID {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
} XrHandMeshGetInfoANDROID;

คำอธิบายสมาชิก

  • type คือ XrStructureType ของโครงสร้างนี้
  • next คือ NULL หรือพอยน์เตอร์ไปยังโครงสร้างถัดไปในเชนโครงสร้าง ไม่มีการกำหนดโครงสร้างดังกล่าวใน OpenXR หลักหรือส่วนขยายนี้
  • baseSpace คือ XrSpace ที่กำหนดพื้นที่อ้างอิงที่จะค้นหาการเปลี่ยนรูปแบบของจุดยอดที่ time
  • time คือ XrTime ที่อธิบายเวลาที่แอปพลิเคชันต้องการค้นหาเมชมือ

การใช้งานที่ถูกต้อง (โดยนัย)

โครงสร้าง XrHandTrackingMeshesANDROID มีข้อมูลเมชสำหรับทั้ง 2 มือ

typedef struct XrHandTrackingMeshesANDROID {
    XrStructureType      type;
    void*                next;
    XrHandMeshANDROID    leftHandMesh;
    XrHandMeshANDROID    rightHandMesh;
} XrHandTrackingMeshesANDROID;

คำอธิบายสมาชิก

  • type คือ XrStructureType ของโครงสร้างนี้
  • next คือ NULL หรือพอยน์เตอร์ไปยังโครงสร้างถัดไปในเชนโครงสร้าง ไม่มีการกำหนดโครงสร้างดังกล่าวใน OpenXR หลักหรือส่วนขยายนี้
  • leftHandMesh คือ XrHandMeshANDROID สำหรับมือซ้าย
  • rightHandMesh คือ XrHandMeshANDROID สำหรับมือขวา

การใช้งานที่ถูกต้อง (โดยนัย)

โครงสร้าง XrHandMeshANDROID มีข้อมูลและบัฟเฟอร์เพื่อรับข้อมูลการติดตามเมชมือจากฟังก์ชัน xrGetHandMeshANDROID สำหรับมือข้างเดียว

typedef struct XrHandMeshANDROID {
    XrBool32             isActive;
    XrTime               dynamicLastUpdateTime;
    uint32_t             indexCount;
    uint32_t             vertexCount;
    const uint32_t*      indices;
    const XrVector2f*    textureUVs;
    const XrVector3f*    positions;
    const XrVector3f*    normals;
    XrPosef              baseSpaceFromVertexSpace;
} XrHandMeshANDROID;

คำอธิบายสมาชิก

  • type คือ XrStructureType ของโครงสร้างนี้
  • next คือ NULL หรือพอยน์เตอร์ไปยังโครงสร้างถัดไปในเชนโครงสร้าง ไม่มีการกำหนดโครงสร้างดังกล่าวใน OpenXR หลักหรือส่วนขยายนี้
  • isActive คือ XrBool32 ซึ่งระบุว่าอุปกรณ์ติดตามเมชบนมือที่ใช้งานอยู่ในปัจจุบันทำงานอยู่และข้อมูลเมชถูกต้องหรือไม่
  • dynamicLastUpdateTime คือ XrTime ที่ระบุเวลาที่อัปเดตบัฟเฟอร์แบบไดนามิกครั้งล่าสุด
  • indexCount คือ uint32_t ที่ทำหน้าที่เป็นจํานวน indices ของมือ ตาข่าย
  • vertexCount คือ uint32_t ที่ทำหน้าที่เป็นจํานวน positions ของตาข่ายมือ นอกจากนี้ ยังสามารถใช้กับ textureUVs หรือ normals ได้เมื่อระบบรองรับ
  • indices คืออาร์เรย์ของ uint32_t ที่แสดงดัชนีของเมชสำหรับสามเหลี่ยมตามลําดับการต่อทวนเข็มนาฬิกา จํานวนค่าที่ชี้ถึงคือ indexCount
  • textureUVs คือ NULL หรืออาร์เรย์ของ XrVector2f ที่แสดงพิกัดเวิร์กเท็กซ์ จํานวนค่าที่ชี้ถึงคือ vertexCount
  • positions คืออาร์เรย์ของ XrVector3f ที่แสดงตำแหน่งเวิร์กเท็กซ์ใน baseSpaceFromVertexSpace จํานวนค่าที่ชี้ถึงคือ vertexCount
  • normals คือ NULL หรืออาร์เรย์ของ XrVector3f ที่แสดงเวิร์กเท็กซ์ นอร์มัลใน baseSpaceFromVertexSpace จํานวนค่าที่ชี้ถึงคือ vertexCount
  • baseSpaceFromVertexSpace คือจุดยอด XrSpace ที่อยู่ใน XrHandMeshGetInfoANDROID::baseSpace เมื่อเรียกใช้ xrGetHandMeshANDROID แอปพลิเคชันสามารถใช้ข้อมูลนี้เพื่อเปลี่ยนรูปแบบพื้นที่พิกัดของจุดยอดและเวกเตอร์ปกติของเมชระหว่างการแสดงผล

เมชมือจะแสดงเป็นรายการสามเหลี่ยม และจุดยอดของสามเหลี่ยมแต่ละรูปจะเรียงตามลำดับทวนเข็มนาฬิกาเมื่อมองจากภายนอกมือ

เมื่อค่า isActive ที่แสดงผลเป็น XR_FALSE แสดงว่าระบบไม่ได้ติดตามมืออยู่ เช่น มืออยู่นอกระยะของเซ็นเซอร์ ไม่ได้โฟกัสอินพุตจากแอปพลิเคชัน หรือแอปพลิเคชันไม่มีสิทธิ์เข้าถึงข้อมูลการติดตามมือ

เมื่อค่า isActive ที่แสดงผลคือ XR_TRUE ระบบจะอัปเดตเมชการติดตามมือที่แสดงใน indices และ positions รวมถึง textureUVs และ normals (หากระบบรองรับ) เป็นข้อมูลล่าสุดของ XrHandMeshGetInfoANDROID::time ที่ส่งไปยังฟังก์ชัน xrGetHandMeshANDROID

หน่วยความจําที่ชี้โดยบัฟเฟอร์เมชมือที่แสดงผลใน XrHandMeshANDROID เป็นของรันไทม์และแชร์กับแอปพลิเคชัน หน่วยความจําจะเข้าถึงได้จากเธรดใดก็ได้จนกว่าจะมีการเรียกใช้ xrBeginFrame ครั้งถัดไปขณะที่ตัวแฮนเดิล XrHandMeshTrackerANDROID ใช้งานได้

  • ค่าที่ indices และ textureUVs ชี้ถึงไม่ใช่แบบไดนามิก
  • ตัวชี้และค่าที่ positions และ normals ชี้ถึงนั้นเป็นแบบไดนามิก ซึ่งทั้ง 2 อย่างอาจเปลี่ยนแปลงระหว่างการเรียกใช้ xrBeginFrame แอปพลิเคชันสามารถใช้ dynamicLastUpdateTime เพื่อตรวจสอบว่าค่ามีการเปลี่ยนแปลงนับตั้งแต่เฟรมล่าสุดหรือไม่ และหลีกเลี่ยงการประมวลผลข้อมูลที่ไม่จำเป็นเมื่อไม่มีการเปลี่ยนแปลง

การใช้งานที่ถูกต้อง (โดยนัย)

  • ต้องเปิดใช้ส่วนขยาย XR_ANDROID_hand_mesh ก่อนจึงจะใช้ XrHandMeshANDROID ได้
  • indices ต้องเป็นพอยน์เตอร์ไปยังค่า uint32_t ที่ถูกต้อง
  • textureUVs ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrVector2f ที่ถูกต้อง
  • positions ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrVector3f ที่ถูกต้อง
  • normals ต้องเป็นพอยน์เตอร์ไปยังโครงสร้าง XrVector3f ที่ถูกต้อง

ตัวอย่างโค้ดสำหรับการติดตามเมชมือ

โค้ดตัวอย่างต่อไปนี้แสดงวิธีเข้าถึงบัฟเฟอร์เมชมือสำหรับการเรนเดอร์

XrInstance instance;  // Created at app startup
XrSystemId systemId;  // Received from xrGetSystem() at app startup
XrSession session;    // Created at app startup.
XrSpace appPlaySpace; // Created at app startup.

// The function pointers are previously initialized using xrGetInstanceProcAddr.
PFN_xrCreateHandMeshTrackerANDROID xrCreateHandMeshTrackerANDROID; // previously initialized
PFN_xrDestroyHandMeshTrackerANDROID xrDestroyHandMeshTrackerANDROID; // previously initialized
PFN_xrGetHandMeshANDROID xrGetHandMeshANDROID; // previously initialized

// Inspect system capability
XrSystemHandMeshTrackingPropertiesANDROID handMeshTrackingProps = {
  .type = XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID,
};
XrSystemProperties sysProps = {
  .type = XR_TYPE_SYSTEM_PROPERTIES,
  .next = &handMeshTrackingProps
};
CHK_XR(xrGetSystemProperties(instance, systemId, &sysProps));
if (!handMeshTrackingProps.supportsHandMeshTracking) {
  // hand mesh tracking is not supported.
  return;
}

XrHandMeshTrackerCreateInfoANDROID trackerCreateInfo = {
  .type = XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
};
XrHandMeshTrackerANDROID handMeshTracker = XR_NULL_HANDLE;
CHK_XR(xrCreateHandMeshTrackerANDROID(
    session, &trackerCreateInfo, &handMeshTracker));
// app update loop
while (true) {
    // ...
    // For every frame in frame loop
    // ...

    XrFrameState frameState;  // previously returned from xrWaitFrame
    const XrTime time = frameState.predictedDisplayTime;

    // ...
    XrHandMeshGetInfoANDROID getInfo = {
        .type = XR_TYPE_HAND_MESH_GET_INFO_ANDROID,
        .baseSpace = appPlaySpace,
        .time = time,
    };
    XrHandTrackingMeshesANDROID handMeshes = {
        .type = XR_TYPE_HAND_TRACKING_MESHES_ANDROID
    };
    CHK_XR(xrGetHandMeshANDROID(handMeshTracker, &getInfo, &handMeshes));

    if (handMeshes.leftHandMesh.isActive) {
        // access vertex/index buffers for rendering.
    }

    // ...
    // Finish frame loop
    // ...
}

CHECK_XR(xrDestroyHandMeshTracker(handMeshTracker));

ประเภทออบเจ็กต์ใหม่

ค่าคงที่ Enum ใหม่

เพิ่มรายการต่อไปนี้ในคําจํากัดความของ XrObjectType

  • XR_OBJECT_TYPE_HAND_MESH_TRACKER_ANDROID

เพิ่มรายการต่อไปนี้ในคําจํากัดความของ XrStructureType

  • XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID
  • XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
  • XR_TYPE_HAND_MESH_GET_INFO_ANDROID
  • XR_TYPE_HAND_TRACKING_MESHES_ANDROID

Enum ใหม่

โครงสร้างใหม่

ฟังก์ชันใหม่

ปัญหา

ประวัติเวอร์ชัน

  • การแก้ไข 1, 10-09-2024 (Levana Chen)
    • คำอธิบายส่วนขยายเริ่มต้น