在ARKit / RealityKit中同时使用水平和垂直平面

时间:2019-11-19 23:25:14

标签: swift scenekit augmented-reality arkit realitykit

我无法在ARKit中同时检测水平和垂直平面。到目前为止,我已经能够成功检测到一定程度的水平面,但是我也希望将其与对垂直平面的支持集成在一起。

我的目标是创建一个AR项目,该项目的球可以从地板和墙壁反弹。在没有垂直平面检测的情况下,球会反弹到远处,直到不再可见为止。

下面是我用于水平面检测的东西。

public func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    let plane = SCNPlane(width: width, height: height)
    plane.materials.first?.diffuse.contents = UIColor.init(white: 1, alpha: 1)
    let planeNode = SCNNode(geometry: plane)
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x,y,z)
    planeNode.eulerAngles.x = -.pi / 2
    scene.rootNode.addChildNode(planeNode)
    let box = SCNBox(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z), length: CGFloat(planeAnchor.extent.y), chamferRadius: 0)
    planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: box, options: nil))
}

如何在ARKit或RealityKit项目中同时具有水平和垂直平面?

1 个答案:

答案 0 :(得分:1)

您可以照常使用以下代码进行操作:

    HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Unlock(void)
    {
      uint32_t primask_bit;

      if((FLASH->PECR & FLASH_PECR_PELOCK) != RESET)
      {  
        /* Disable interrupts to avoid any interruption during unlock sequence */
        primask_bit = __get_PRIMASK();
        __disable_irq();

        /* Unlocking the Data memory and FLASH_PECR register access*/
        FLASH->PEKEYR = FLASH_PEKEY1;
        FLASH->PEKEYR = FLASH_PEKEY2;

        /* Re-enable the interrupts: restore previous priority mask */
        __set_PRIMASK(primask_bit);

        if((FLASH->PECR & FLASH_PECR_PELOCK) != RESET)
        {
          return HAL_ERROR;
        }
      }

      return HAL_OK;  
    }

HAL_StatusTypeDef   HAL_FLASHEx_DATAEEPROM_Program(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
{
  HAL_StatusTypeDef status = HAL_ERROR;

  /* Process Locked */
  __HAL_LOCK(&pFlash);

  /* Check the parameters */
  assert_param(IS_TYPEPROGRAMDATA(TypeProgram));
  assert_param(IS_FLASH_DATA_ADDRESS(Address));

  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);

  if(status == HAL_OK)
  {
    /* Clean the error context */
    pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;

    if(TypeProgram == FLASH_TYPEPROGRAMDATA_WORD)
    {
      /* Program word (32-bit) at a specified address.*/
      *(__IO uint32_t *)Address = Data;
    }
    else if(TypeProgram == FLASH_TYPEPROGRAMDATA_HALFWORD)
    {
      /* Program halfword (16-bit) at a specified address.*/
      *(__IO uint16_t *)Address = (uint16_t) Data;
    }
    else if(TypeProgram == FLASH_TYPEPROGRAMDATA_BYTE)
    {
      /* Program byte (8-bit) at a specified address.*/
      *(__IO uint8_t *)Address = (uint8_t) Data;
    }
    else
    {
      status = HAL_ERROR;
    }

    if (status != HAL_OK)
    {
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    }
  }

  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);

  return status;
}

HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{
  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
     Even if the FLASH operation fails, the BUSY flag will be reset and an error
     flag will be set */

  uint32_t tickstart = HAL_GetTick();

  while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) 
  { 
    if (Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
      {
        return HAL_TIMEOUT;
      }
    }
  }

  /* Check FLASH End of Operation flag  */
  if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
  {
    /* Clear FLASH End of Operation pending bit */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
  }

  if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)     || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)     || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)     || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)    || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)      || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR)     || 
      __HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR) )
  {
    /*Save the error code*/

    /* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
     *           (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
     *           as expected. If the user run an application using the first
     *           cut of the STM32L031xx device or the first cut of the STM32L041xx
     *           device, this error should be ignored. The revId of the device
     *           can be retrieved via the HAL_GetREVID() function.
     *
     */
    FLASH_SetErrorCode();
    return HAL_ERROR;
  }

  /* There is no error flag set */
  return HAL_OK;
}

override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let configuration = ARWorldTrackingConfiguration() configuration.planeDetection = [.horizontal, .vertical] arView.session.run(configuration) } 实例属性是可获取和可设置的:

planeDetection

...和 var planeDetection: ARWorldTrackingConfiguration.PlaneDetection { get set } struct 符合OptionSet协议,该协议允许您仅使用一个值或同时使用两个值时间:

PlaneDetection

然后将 renderer(_:didAdd:for:)实例方法添加到您的代码中,如下所示:

configuration.planeDetection = []
configuration.planeDetection = .vertical
configuration.planeDetection = [.horizontal, .vertical]

最后,添加可能如下所示的 renderer(_:didUpdate:for:)实例方法:

func renderer(_ renderer: SCNSceneRenderer,
             didAdd node: SCNNode,
              for anchor: ARAnchor) {

    guard let planeAnchor = anchor as? ARPlaneAnchor 
    else { return }

    let width = CGFloat(planeAnchor.extent.x)
    let height = CGFloat(planeAnchor.extent.z)
    let myPlane = SCNPlane(width: width, height: height)           

    if planeAnchor.alignment == .horizontal {
        myPlane.materials.first?.diffuse.contents = UIColor.semiOpaqueRed
    } else if planeAnchor.alignment == .vertical {
        myPlane.materials.first?.diffuse.contents = UIColor.semiOpaqueCyan
    }

    let planeNode = SCNNode(geometry: myPlane)
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)

    planeNode.position = SCNVector3(x, y, z)
    planeNode.eulerAngles.x = -.pi / 2

    node.addChildNode(planeNode)
}