XGRIDSДокументация
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • Lixel CyberColor

    • Руководство пользователя LCC Studio

      • Начало работы
      • Версия и обновления
      • Загрузка и установка
      • Обзор интерфейса и навигация
      • Перед реконструкцией
      • Реконструкция модели
      • Реконструкция одиночной модели
      • Объединение карт
      • Воздушно-наземное объединение
      • Воздушная реконструкция
      • Мои модели
      • Другие функции
      • Настройки и учётная запись
      • Конвертер
      • Реконструкция по видео
      • Часто задаваемые вопросы
    • LCC Scene Editor

      • Версия и обновления
      • Учётная запись и вход
      • Обзор продукта и главная страница
      • Интерфейс редактора
      • Режимы навигации по сцене
      • Файл
      • Настройки
      • Операции редактирования
      • Окно
      • Глобальная панель инструментов
      • Ресурсы и свойства
      • Левая панель инструментов
      • Точки обзора
      • Портал
      • Skybox
      • Аннотации
      • Измерение
      • Flythrough
      • Отчёт по сцене
      • 3D Layout
      • Мини-карта
      • Preview Mode (Viewer)
      • Справка
      • Часто задаваемые вопросы
      • Точка появления
    • LCC Model Editor

      • Версия и обновления
      • Руководство пользователя
      • Обзор и интерфейс
      • Операции с файлами
      • Инструменты выбора
      • Редактирование моделей
      • Измерение
      • Цветокоррекция
      • Управление ресурсами
      • Настройки и справка
      • Часто задаваемые вопросы
    • Рекомендации по применению

      • Объединение нескольких крупных моделей 3DGS
  • Plugin & SDK

    • Unreal

      • Введение
      • Быстрый старт — Windows
      • Быстрый старт — Linux
      • Быстрый старт — Quest3
      • Редакции и лицензирование
      • Рендеринг
      • Растеризация Tiled (экспериментально)
      • Визуальные настройки
      • Нормали и освещение
      • Редактирование сцены
      • Параметры производительности
      • Руководство по оптимизации производительности
      • Интеграция со сторонними и движковыми плагинами
      • Прокси-меш
      • Анимация загрузки
      • Коллизии
      • Поддержка системы навигации
      • Поддержка однослойной воды
      • Локализация
      • Частые вопросы
      • Устранение неполадок
      • Журналы и диагностика
      • Свяжитесь с нами
      • Рекомендуемые практики

        • Переосвещение 3DGS с помощью меша LixelStudio
      • Справочник API

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • Actor SOG / SPZ / PLY
        • ALCC2ProxyMesh
        • ALCCClippingVolume
        • ALCCSectionPlane
        • ALCCLoadVolume
        • ULCCUtilLibrary
        • Enums
        • Structs
      • Журнал изменений

        • v3.4.0
        • v3.3.1
        • v3.0.0
        • v2.2.1
        • v1.0.0
        • v0.9.0
        • v0.8.0
        • v0.7.1
        • v0.6.1
        • v0.5.2
        • v0.4.1
        • v0.4.0
        • v0.3.0
        • v0.0.5
        • v0.0.4
        • v0.0.3
        • v0.0.2
        • v0.0.1
    • Unity

      • Введение в Unity SDK
      • Технические возможности
      • Требования к среде разработки
      • Руководство по быстрому старту для PC
      • Руководство по оптимизации настроек проекта
      • Руководство по разработке для Pico 4 Ultra
      • Руководство по стримингу Pico 4 Ultra с PC
      • Руководство по разработке для Quest 3
      • Руководство по стримингу Quest 3 с PC
      • Руководство по разработке OpenXR
      • Руководство по бизнес-стримингу Pico 4 Ultra
      • Глоссарий
      • FAQ
      • Свяжитесь с нами
      • Руководство по разработке функций

        • Руководство по разработке смешанного рендеринга нескольких сцен
        • Руководство по разработке приёма теней
        • Руководство по разработке освещения в реальном времени
        • Руководство по разработке многокамерного рендеринга
        • Руководство по разработке рендеринга изображений высокого разрешения
        • Руководство по разработке совместимости форматов данных LCC и LCC2
        • Руководство по разработке эффекта загрузки
        • Руководство по разработке переключения режима рендеринга Mip
        • Руководство по разработке привязки к рёбрам и углам
        • Руководство по разработке проецируемых декалей
        • Руководство по разработке видеопроецируемой декали
        • Руководство по разработке подсветки
        • Руководство по разработке обрезки в реальном времени
        • Руководство по разработке коррекции цвета
        • Руководство по разработке получения данных Mesh сцены
        • Руководство по разработке в режиме редактора
        • Руководство по настройке параметров производительности рендеринга
        • Руководство по разработке совместной упаковки приложения и данных
        • Руководство по разработке системы коллизий
        • Руководство по проблемам с разрешениями при разработке на macOS
        • Руководство по разработке компиляции и упаковки для устройств iOS
      • Справочник по API

        • LCCManager
        • Renderer
        • Типы данных
      • Журнал изменений

        • v2.3.0
        • v2.2.10
        • v2.2.0
        • v2.1.19
        • v2.0.14

Руководство по разработке привязки к рёбрам и углам

LCC Unity SDK поддерживает обнаружение рёбер и углов и предпросмотр привязки на поверхностях 3DGS, что можно использовать в сценариях взаимодействия, требующих точного позиционирования, таких как измерение, аннотирование и размещение. Ниже описаны полные шаги по реализации обнаружения рёбер/углов и привязки.

Примечание:

Функция привязки (обнаружение рёбер/углов, предпросмотр привязки и рейкастинг с привязкой) поддерживается только на платформах PC / Mac. Вызов связанных API на платформах mobile / VR не даёт эффекта и выводит предупреждение.

Шаг 1: Создайте сцену и GameObject

Создайте совершенно новую сцену в Unity. Unity по умолчанию создаёт Main Camera и Directional Light.

Настройте Main Camera

Выберите Main Camera в окне Hierarchy и задайте его свойства в окне Inspector, как показано ниже.

Настройка свойств Main Camera

Настройка свойств Main Camera

Создайте LCCManager

Щёлкните правой кнопкой мыши в пустой области окна Hierarchy, выберите Create Empty во всплывающем меню, чтобы создать пустой GameObject, назовите его LCCManager, нормализуйте его Transform и добавьте к нему скрипт LCCManager через Add Component.

Создание GameObject LCCManager и добавление скрипта LCCManager

Создание GameObject LCCManager и добавление скрипта LCCManager

Создайте LCCRenderer

Щёлкните правой кнопкой мыши в пустой области окна Hierarchy, выберите Create Empty, чтобы создать пустой GameObject, назовите его LCCRenderer и задайте его Transform значения Rotation.x = -90 и Scale.x = -1.

Создание LCCRenderer и настройка его Transform

Создание LCCRenderer и настройка его Transform (Rotation.x = -90, Scale.x = -1)

Примечание:

Настройки Transform GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) выравнивают его с системой координат данных LCC. Подробнее о выравнивании системы координат см. в разделе «Система координат данных LCC» документа Введение в Unity SDK.

Шаг 2: Добавьте Render Feature

  1. В строке меню Unity выберите File → Project Settings, выберите Graphics слева и подтвердите текущий Default Render Pipeline Asset. В этом примере используется URP (Universal Render Pipeline Asset).
Подтверждение Default Render Pipeline Asset в настройках Graphics

Подтверждение Default Render Pipeline Asset в настройках Graphics

  1. Щёлкните по этому Asset, найдите соответствующий файл ассета в окне Project и найдите связанный с ним Renderer (URP_Renderer.asset в этом примере).

  2. Выберите этот файл ассета Renderer, нажмите Add Renderer Feature в окне Inspector и добавьте Snap Frame Capture Feature.

Добавление Snap Frame Capture Feature в URP Renderer

Добавление Snap Frame Capture Feature в URP Renderer

Шаг 3: Напишите скрипт для включения привязки

Создайте новый скрипт C# с именем Snap.cs со следующим кодом:

using LCCCore;
using UnityEngine;

public class Snap : MonoBehaviour
{
    public LCCManager m_manager;
    public string m_FilePath;
    private LCCCore.Renderer m_renderer;
    private bool m_loaded = false;
    private Camera m_camera;

    void Start()
    {
        m_camera = Camera.main;
        m_manager.SetPlatformType(PlatformType.PC);
        Debug.Log("Запущено ");
        m_renderer = m_manager.GetRender(this.transform);
        m_renderer.Load(m_FilePath, onProgress, onComplete);
    }

    private void onProgress(float _progress)
    {
        Debug.Log($"[LCCRenderer] прогресс загрузки файла: {_progress:P1}");
    }

    private void onComplete()
    {
        Debug.Log($"[LCCRenderer] файл загружен");
        m_loaded = true;
        // Включаем обнаружение рёбер/углов и предпросмотр привязки
        m_manager.SetSnapEnabled(true);
        m_manager.SetSnapPreviewEnabled(true);
    }

    private void Update()
    {
        if (!m_loaded) return;
        // Обновляем предпросмотр привязки в реальном времени на основе текущей позиции мыши
        m_manager.UpdateSnapPreview(Input.mousePosition, m_camera);
        if (Input.GetMouseButtonDown(1))
        {
            m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult result);
            if (result.isHit)
            {
                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = result.hitPos;
                sphere.GetComponent<UnityEngine.Renderer>().material.color = Color.red;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }
    }
}

Примечание:

Обнаружение рёбер/углов (SetSnapEnabled) и предпросмотр привязки (SetSnapPreviewEnabled) должны включаться после завершения загрузки LCC-сцены, поэтому оба вызываются в обратном вызове onComplete. Предпросмотр привязки также нужно непрерывно обновлять через UpdateSnapPreview в Update.

Приведённый выше пример демонстрирует следующие моменты:

  • Включение обнаружения рёбер и углов: m_manager.SetSnapEnabled(true)
  • Включение предпросмотра привязки: m_manager.SetSnapPreviewEnabled(true)
  • Обновление предпросмотра привязки в реальном времени: m_manager.UpdateSnapPreview(Input.mousePosition, m_camera)
  • Рейкастинг в точке привязки и создание сферы в точке попадания: m_manager.RaycastWithSnap(...); при попадании в точке result.hitPos создаётся красная сфера

Шаг 4: Прикрепите скрипт и задайте путь к данным

  1. Прикрепите скрипт Snap.cs к GameObject LCCRenderer в окне Hierarchy.
  2. В окне Inspector перетащите GameObject LCCManager на свойство Manager скрипта.
  3. Заполните путь к файлу LCC в свойстве File Path скрипта.

Шаг 5: Запустите

Нажмите кнопку Play в окне Game, чтобы увидеть обнаруженные в реальном времени рёбра и углы и значок предпросмотра цели привязки. При движении мыши значок предпросмотра следует за ближайшей целью привязки в реальном времени; щелчок правой кнопкой выполняет рейкастинг в точке привязки и создаёт красную сферу.

Рёбра, углы и значок предпросмотра привязки, обнаруженные в реальном времени после запуска

Рёбра, углы и значок предпросмотра привязки, обнаруженные в реальном времени после запуска

FAQ: Отключите режим совместимости

Если окно Console Unity сообщает об ошибках и значок предпросмотра привязки не появляется, отключите режим совместимости: откройте панель настроек через Edit → Project Settings → Graphics, выберите вкладку URP и не отмечайте флажок после Render Graph → Compatibility Mode (Render Graph Disabled).

Не отмечайте режим совместимости Render Graph

Не отмечайте режим совместимости Render Graph (Render Graph Disabled)

Ключевые шаги

Ключевые шаги для реализации обнаружения рёбер/углов и привязки:

  1. Убедитесь, что Snap Frame Capture Feature добавлен в URP Renderer.
  2. Убедитесь, что обнаружение рёбер/углов (SetSnapEnabled(true)) и предпросмотр привязки (SetSnapPreviewEnabled(true)) включены в коде после завершения загрузки LCC-сцены.
  3. Убедитесь, что UpdateSnapPreview вызывается в реальном времени в Update для обновления значка предпросмотра.

API, связанные с привязкой

LCC Unity SDK предоставляет следующие API, связанные с привязкой, через LCCManager. Они поддерживаются только на платформах PC / Mac — вызов на платформах mobile / VR не даёт эффекта и выводит предупреждение — и все они должны вызываться после завершения загрузки LCC-сцены.

SetSnapEnabled

// Возвращаемое значение: void
public void SetSnapEnabled(bool enable)

Переключает функцию привязки. При включении RaycastWithSnap автоматически ищет ближайшие рёбра/углы для привязки.

ПараметрТипОписание
enableboolВключать ли привязку

Пример использования:

m_manager.SetSnapEnabled(true);

Примечания:

  • Отключено по умолчанию.
  • Поддерживается только на PC / Mac; вызов на mobile / VR не даёт эффекта и выводит предупреждение.
  • При включении выделяются ресурсы GPU (EdgeDetect / CornerDetect / SnapSearch).

SetSnapRadius

// Возвращаемое значение: void
public void SetSnapRadius(float pixels)

Задаёт радиус поиска привязки. Ближайшее ребро/угол ищется в пределах этого пиксельного диапазона.

ПараметрТипОписание
pixelsfloatРадиус поиска привязки (в пикселях)

Пример использования:

m_manager.SetSnapRadius(30f);

Примечания:

  • По умолчанию 20 пикселей.
  • Чем больше значение, тем шире диапазон поиска, но может привязаться к нежелательным целям.
  • Поддерживается только на PC / Mac.

SetEdgeThreshold

// Возвращаемое значение: void
public void SetEdgeThreshold(float threshold)

Задаёт порог обнаружения рёбер Собеля. Чем меньше значение, тем больше рёбер обнаруживается.

ПараметрТипОписание
thresholdfloatПорог обнаружения рёбер

Пример использования:

m_manager.SetEdgeThreshold(0.2f);

Примечания:

  • По умолчанию 0.3.
  • Рекомендуемый диапазон [0.1, 0.8].
  • Слишком маленькое значение даёт много шумных рёбер.
  • Поддерживается только на PC / Mac.

SetSnapPreviewEnabled

// Возвращаемое значение: void
public void SetSnapPreviewEnabled(bool enable)

Переключает функцию предпросмотра привязки. При включении индикатор ближайшей цели привязки отображается в реальном времени при движении мыши.

ПараметрТипОписание
enableboolВключать ли предпросмотр привязки

Пример использования:

m_manager.SetSnapPreviewEnabled(true);

Примечания:

  • Требует предварительного вызова SetSnapEnabled(true).
  • Предпросмотр постоянно потребляет ресурсы GPU (обнаружение каждый кадр).
  • Поддерживается только на PC / Mac.

UpdateSnapPreview

// Возвращаемое значение: void
public void UpdateSnapPreview(Vector2 mousePos, Camera cam)

Обновляет состояние предпросмотра привязки. Вызывайте при движении мыши, чтобы обновить позицию индикатора предпросмотра.

ПараметрТипОписание
mousePosVector2Текущая экранная координата мыши
camCameraКамера

Пример использования:

void Update()
{
    m_manager.UpdateSnapPreview(Input.mousePosition, Camera.main);
}

Примечания:

  • Требует предварительного вызова SetSnapPreviewEnabled(true).
  • Рекомендуется вызывать непрерывно в Update.
  • Поддерживается только на PC / Mac.

GetSnapPreviewState

// Возвращаемое значение: SnapPreviewState (screenPos в экранных координатах)
public SnapPreviewState GetSnapPreviewState()

Получает текущее состояние предпросмотра привязки, включая наличие цели привязки, тип цели, экранную позицию цели и пиксельное расстояние до мыши.

Пример использования:

var state = m_manager.GetSnapPreviewState();
if (state.hasTarget)
{
    // state.snapType: угол / ребро
    // state.screenPos: экранная позиция цели привязки
    // state.distanceToMouse: расстояние в пикселях
}

Примечания:

  • Требует предварительного вызова SetSnapPreviewEnabled(true) и UpdateSnapPreview.
  • Возвращает default(SnapPreviewState) при отсутствии цели.
  • screenPos — это экранная координата, а не мировая; если нужна мировая координата, используйте RaycastWithSnap для получения HitResult.hitPos.
  • Поддерживается только на PC / Mac.

RaycastWithSnap

// Возвращаемое значение: bool (true = попадание)
public bool RaycastWithSnap(Vector2 screenPos, Camera cam, out HitResult result)

Рейкастинг с привязкой. Сначала выполняется обычный Raycast, затем ищутся рёбра/углы рядом с точкой попадания для привязки.

ПараметрТипОписание
screenPosVector2Экранная координата
camCameraКамера
resultout HitResultРезультат попадания (включая информацию о привязке)

Пример использования:

if (m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult hit))
{
    // hit.snapType: угол / ребро / нет
    // hit.hitPos: мировая позиция после привязки
    // hit.originalHitPos: исходная точка попадания до привязки
}

Примечания:

  • Требует предварительного вызова SetSnapEnabled(true).
  • Приоритет привязки: угол > ребро > нет.
  • Эта точка входа синхронно блокирует основной поток (ожидая результат чтения с GPU); рекомендуется вызывать её только на событиях взаимодействия (например, клики), а не каждый кадр.
  • В режиме предпросмотра (SetSnapPreviewEnabled(true)), если цель привязки уже существует, кэш предпросмотра используется повторно без пересчёта; иначе используется обычный поток привязки.
  • Поддерживается только на PC / Mac.

Связанные структуры данных

SnapType

public enum SnapType { None, Edge, Corner }

Тип цели привязки: нет / ребро / угол.

SnapPreviewState

public struct SnapPreviewState {
    public bool hasTarget;          // есть ли цель привязки
    public SnapType snapType;       // нет / ребро / угол
    public Vector2 screenPos;       // экранная позиция цели привязки (не мировая позиция)
    public float distanceToMouse;   // расстояние в пикселях до позиции мыши
}

⚠️ screenPos — это экранная пиксельная координата, а не мировая. Если нужна мировая координата, используйте RaycastWithSnap для получения HitResult.hitPos.

HitResult

public struct HitResult {
    public bool isHit;             // есть ли попадание
    public float distance;         // расстояние
    public Vector3 hitPos;         // мировая позиция точки попадания (имя поля hitPos, а не position)
    public Vector3 normal;         // нормаль попадания
    public float hitAlpha;         // альфа попавшего эллипсоида
    public float dist2Origin;      // расстояние до начала луча
    public float scale;            // масштаб эллипсоида
    public SnapType snapType;      // тип привязки (нет / ребро / угол)
    public Vector3 originalHitPos; // исходная точка попадания до привязки
}

⚠️ Различие в именах полей: поле для мировой позиции точки попадания называется hitPos (а не position); вызывающий код должен обращаться к нему по фактическому имени поля.