How to geometrically align a 3D model to real furniture?
For my video-see-through AR application I want a model to automatically be placed on the biggest found table surface. I achieved the first step: The model is correctly positioned at the table center. However, the orientationis not correct. I want the model to "lie down" on the table, means laying on the back, facing up, while the longest side of the model is orientated just as the longest side of the table - see the following pictures:
After a very long time trying, I could not figure out how to align the model correctly. If you have any idea/hint/ or clue I could try, please let me know.
Used Asset for testing:
I added an Empty (called ModelPlacer) where I added the script (see below) and pulled this asset in the modelInstance field.
Used Meta XR Building Blocks:
- Camera Rig
- Passthrough
- MR Utility Kit
- Scene Debugger
- Effect Mesh
- Hand Tracking
- Controller Tracking
Technical Specifications:
- Unity 2022.3.50f1
- VR-Glasses: Meta Quest 3
- Meta MR Utility Kit
Code:
using Meta.XR.MRUtilityKit;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ModelPlacer : MonoBehaviour
{
public GameObject modelPrefab;
private GameObject modelInstance;
void Start()
{
MRUK.Instance?.RegisterSceneLoadedCallback(OnSceneLoaded);
}
private void OnSceneLoaded()
{
SpawnModel();
AlignModelWithSurface();
}
public void SpawnModel()
{
Vector3 spawnPosition = new Vector3(0.0f, 1.0f, -1.0f);
modelInstance = Instantiate(modelPrefab, spawnPosition, Quaternion.identity);
}
public void AlignModelWithSurface()
{
var largestSurface = MRUK.Instance?.GetCurrentRoom()?.FindLargestSurface(MRUKAnchor.SceneLabels.TABLE);
if (modelInstance != null)
{
if (largestSurface != null)
{
modelInstance.transform.SetParent(largestSurface.transform);
Renderer modelRenderer = modelInstance.GetComponent<Renderer>();
modelInstance.transform.rotation = Quaternion.Euler(-90, 0, 0);
Vector3 modelCenter = modelRenderer.bounds.center;
Vector3 surfaceCenter = largestSurface.transform.position;
Vector3 positionOffset = surfaceCenter - modelCenter;
Vector3 adjustedPosition = modelInstance.transform.position + positionOffset;
modelInstance.transform.position = adjustedPosition;
}
else
{
Debug.LogWarning("No surface found.");
}
}
else
{
Debug.LogWarning("modelInstance is null.");
}
}
}