Guide de développement de la découpe en temps réel
Le LCC Unity SDK prend en charge des opérations d'édition telles que le surlignage et la découpe sur les scènes 3DGS. Ce guide présente les opérations de découpe en temps réel : sélectionner une zone via des textures projetées 2D, une géométrie 3D, ou un mélange des deux, découpant la zone sélectionnée hors de la scène, avec prise en charge de la sélection normale et de la sélection inversée.
Remarque :
La fonctionnalité de découpe actuelle n'est qu'un effet d'affichage à l'exécution ; elle ne modifie en aucune façon le fichier de données d'origine et ne prend pas en charge l'enregistrement ou l'exportation du résultat d'édition. Si vous devez ajuster les couleurs, découper et enregistrer des données, utilisez l'outil logiciel XGRIDS LCC Editor.
Si vous ne souhaitez pas modifier les données, vous pouvez également enregistrer les opérations et les rejouer après la fin du chargement des données la prochaine fois.
Prérequis
La découpe d'une scène via le SDK nécessite les conditions suivantes :
- Entrer dans l'état d'édition avant de charger les données. Le SDK est dans l'état de navigation (View) par défaut, qui offre les meilleures performances et est recommandé pour la navigation normale. Pour effectuer des opérations d'édition telles que la découpe, passez à l'état d'édition via
SetEditorMode(true)avant d'appelerLoad. Cette méthode ne prend effet que si elle est appelée avant le chargement de toutes les données. - Effectuer l'opération de découpe après la fin du chargement des données. L'interface de découpe doit être appelée après le chargement complet des données de la scène.
Étape 1 : Configurer la scène
Préparez les GameObjects nécessaires à la découpe dans la scène comme illustré ci-dessous.

Structure de hiérarchie de la scène pour l'exemple de découpe
- Caméra principale : la caméra de la scène ; la découpe 2D utilise ses matrices de vue et de projection.
- LCCManager : un GameObject vide avec un Transform normalisé, avec le script
LCCManagerajouté. - LCCRenderer : un GameObject vide avec Transform défini sur Rotation.x = -90, Scale.x = -1 (aligné avec le système de coordonnées des données LCC), utilisé pour attacher le script
Clipécrit plus tard. - Géométrie de sélection 3D : objets auxiliaires pour la découpe 3D. L'exemple prépare 3 Cubes (
Box1,Box2,Box3) et 1 Sphère (Clipsphere) ; déplacer et mettre à l'échelle ces objets contrôle la position et la taille de la sélection de découpe.
Remarque :
Pour les réglages liés à la caméra de rendu, aux GameObjects LCCManager et LCCRenderer, reportez-vous aux sections pertinentes du Guide de démarrage rapide PC et du Guide d'optimisation des paramètres de projet.

Géométrie de sélection utilisée pour la découpe 3D (Box1 / Box2 / Box3 / Clipsphere)
Étape 2 : Comprendre les structures de données
La découpe implique trois méthodes d'opération — 2D, 3D et mixte 2D/3D. Les enums et structs utilisés sont les suivants.
public enum SelectMode { normal, invert, clip } // sélection normale, inversion, découpe en temps réel
public enum OperationMode { normal, erase } // sélection normale, effacement de la sélection
public enum ShapeType { box, sphere } // sélection par boîte 3D, sélection par sphère 3D
public enum EditType { Edit2D, Edit3D } // édition 2D, édition 3D
// Sélection par texture 2D
public struct Data2D
{
public Texture2D texture; // texture de masque 2D
public Matrix4x4 mv; // matrice de vue de la caméra
public Matrix4x4 mvp; // matrice de vue-projection de la caméra
public SelectMode mode; // mode de sélection
}
// Sélection par géométrie 3D
public struct Data3D
{
public ShapeType type; // type de géométrie (box / sphere)
public Matrix4x4 invMat; // matrice monde-vers-local (inverse) de la géométrie
public OperationMode operation; // type d'opération (union normale / différence par effacement)
public SelectMode mode; // mode de sélection
}
// Sélection mixte 2D / 3D
public struct DataMix
{
public EditType editType; // type d'édition (requis ; détermine si les champs 2D ou 3D sont utilisés)
public Texture2D texture; // texture de masque 2D (utilisée par Edit2D)
public Matrix4x4 mv; // matrice de vue de la caméra (utilisée par Edit2D)
public Matrix4x4 mvp; // matrice de vue-projection de la caméra (utilisée par Edit2D)
public ShapeType type; // type de géométrie (utilisé par Edit3D)
public Matrix4x4 invMat; // matrice inverse de la géométrie (utilisée par Edit3D)
public OperationMode operation; // type d'opération (utilisé par Edit3D)
public SelectMode mode; // mode de sélection (requis)
}
Il y a trois points à noter concernant la liste de sélection :
- La liste est ordonnée. Qu'il s'agisse de 2D ou de 3D, les entrées de la liste prennent effet dans l'ordre ; assurez-vous que l'ordre d'ajout correspond à votre attente.
- Invert est une commande d'opération et n'a pas besoin d'être associée à des données de sélection spécifiques. Ajoutez simplement une entrée avec
mode = SelectMode.invertpour inverser la zone actuellement sélectionnée. - Le nombre maximum d'entrées dans une seule liste est de 255. Le dépasser retourne un code d'erreur.
Étape 3 : Comprendre les API de découpe
Toutes les interfaces liées à la découpe sont fournies par LCCManager, incluant trois surcharges de SetClip et une méthode de sortie.
SetClip (découpe par texture 2D)
// Valeur de retour : int
// 0 : succès
// 1 : la liste est nulle ou comporte 0 élément
// 2 : les éléments de la liste dépassent le maximum de 255
public int SetClip(List<Data2D> _2Ds)
Découpe la scène à l'aide d'un masque de texture projetée 2D ; la zone marquée est découpée hors de la scène.
SetClip (découpe par géométrie 3D)
// Valeur de retour : int
// 0 : succès
// 1 : la liste est nulle ou comporte 0 élément
// 2 : les éléments de la liste dépassent le maximum de 255
// 3 : le nombre de boîtes de géométrie de sélection est 0
public int SetClip(List<Data3D> _3Ds)
Définit la zone de découpe à l'aide de la géométrie 3D (cuboïde, cube, sphère), prenant en charge les combinaisons d'union et de différence. Au moins une géométrie avec operation == OperationMode.normal est requise.
SetClip (découpe en mode mixte)
// Valeur de retour : int
// 0 : succès
// 1 : la liste est nulle ou comporte 0 élément
// 2 : les éléments de la liste dépassent le maximum de 255
public int SetClip(List<DataMix> _Mix)
Définit la zone de découpe en utilisant des textures 2D et une géométrie 3D en même temps ; chaque entrée détermine si elle est traitée comme 2D ou 3D via editType.
QuitClipMode
// Valeur de retour : void
public void QuitClipMode()
Sort du mode de découpe et restaure l'affichage complet de la scène.
Conseil :
Les trois surcharges de
SetClipsont mutuellement exclusives. Lors du changement de méthode de découpe ou de l'effacement de la découpe actuelle, appelez d'abordQuitClipMode()puis définissez la nouvelle découpe.
Étape 4 : Spécification de la texture de masque 2D
La découpe 2D décrit la sélection via une texture de masque, prenant en charge diverses méthodes de sélection telles que les quadrilatères, les triangles, les pinceaux et les lassos — il suffit de marquer les pixels correspondants dans la texture avec la valeur de découpe. Lors de l'utilisation d'opérations 2D, la caméra doit être verrouillée et la texture marquée depuis un point de vue fixe. La texture et les valeurs de pixel suivent les conventions suivantes :
- La texture est fixée à 1024 × 1024,
R8monocanal, sans Mipmap, filtrage par points (FilterMode.Point), et échantillonnage borné (TextureWrapMode.Clamp). - Conventions de valeurs de pixel :
| Valeur de pixel | Signification |
|---|---|
128 | Défaut (conserver) |
240 | Sélectionné |
180 | Désélectionner (effacer la zone déjà sélectionnée) |
0 | Découpe |
Dans un scénario de découpe, seules les deux valeurs 128 (défaut conserver) et 0 (découpe) sont généralement utilisées.
Étape 5 : Écrire le script
Créez un nouveau script C# nommé Clip.cs. Complétez d'abord le squelette de base : dans Start, entrez dans l'état d'édition et chargez les données ; après la fin du chargement, définissez le drapeau de chargement que les méthodes de découpe suivantes vérifieront.
using LCCCore;
using System.Collections.Generic;
using UnityEngine;
public class Clip : MonoBehaviour
{
public LCCManager m_manager;
public string m_FilePath;
public GameObject m_Box1;
public GameObject m_Box2;
public GameObject m_Box3;
public GameObject m_Clipsphere;
private LCCCore.Renderer m_renderer;
private Camera m_camera;
private bool m_isLoaded = false;
void Start()
{
m_camera = Camera.main;
m_manager.SetPlatformType(PlatformType.PC);
// Entrer en mode édition ; doit être appelé avant Load
m_manager.SetEditorMode(true);
m_renderer = m_manager.GetRender(this.transform);
if (m_renderer == null)
Debug.LogError("Échec de GetRender, vérifiez que le manager est correctement défini et que le chemin du fichier est valide.");
m_renderer.Load(m_FilePath, onLoadProgress, onLoadCallback);
}
private void onLoadProgress(float value)
{
Debug.Log($"progression du chargement : {value}");
}
private void onLoadCallback()
{
Debug.Log("données chargées !!!");
m_isLoaded = true;
// Désactiver le rendu de l'environnement (nuage de points lointain à faible précision) pour mieux observer le résultat de la découpe
m_renderer.SetEnvironment(false);
}
// Méthodes de découpe 2D / 3D / mixte ci-dessous
}
Remarque :
SetEditorMode(true)doit être appelé avantLoadpour prendre effet ; etSetClipdoit être appelé après la fin du chargement des données (après le déclenchement du callbackonLoadCallback).SetEnvironment(false)désactive le nuage de points d'environnement lointain pour rendre le résultat de la découpe plus clair ; décidez de l'appeler selon les besoins.
Étape 6 : Attacher le script et définir les propriétés
- Attachez le script
Clip.csau GameObject LCCRenderer. - Dans la fenêtre Inspecteur, faites glisser le GameObject LCCManager sur la propriété Manager du script.
- Renseignez le chemin du fichier LCC dans la propriété File Path.
- Faites glisser
Box1,Box2,Box3etClipspherede la scène sur les propriétés correspondantes du script respectivement.

Définir les propriétés du script Clip dans l'Inspecteur
Étape 7 : Exemples d'opération de découpe
Ajoutez les méthodes ci-dessous à la classe Clip, et appelez la méthode correspondante après l'exécution et après la fin du chargement des données.
Découpe par texture 2D
Construisez deux textures de masque R8, marquez les pixels à découper comme 0 et le reste de la zone à conserver comme 128, puis construisez Data2D avec les matrices de la caméra et ajoutez-les à la liste.
public void on2DClip()
{
// La taille de la texture est fixée à 1024*1024 ; gardez les autres propriétés identiques à l'exemple
Texture2D _texture = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture.filterMode = FilterMode.Point;
_texture.wrapMode = TextureWrapMode.Clamp;
int _count = 1024 * 1024;
int _half = _count / 2;
byte[] _values = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i < _half)
_values[i] = 0; // 0 signifie découpe, 128 signifie défaut, 240 signifie sélectionné
else
_values[i] = 128;
}
_texture.SetPixelData(_values, 0);
Texture2D _texture2 = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture2.filterMode = FilterMode.Point;
_texture2.wrapMode = TextureWrapMode.Clamp;
byte[] _values2 = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i > _count * 0.75 && i < _count * 0.9)
_values2[i] = 0;
else
_values2[i] = 128;
}
_texture2.SetPixelData(_values2, 0);
List<Data2D> _2Ds = new List<Data2D>();
Data2D _2d01 = new Data2D();
_2d01.mv = m_camera.worldToCameraMatrix;
_2d01.texture = _texture;
_2d01.mode = SelectMode.normal;
_2d01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_2Ds.Add(_2d01);
Data2D _2d02 = new Data2D();
_2d02.mv = m_camera.worldToCameraMatrix;
_2d02.texture = _texture2;
_2d02.mode = SelectMode.normal;
_2d02.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_2Ds.Add(_2d02);
m_manager.SetClip(_2Ds);
}
Explication du code : deux textures de masque sont construites. Le premier masque découpe la moitié inférieure de l'écran (l'origine de l'écran est le coin inférieur gauche), et le second masque découpe la région de 0.75 à 0.9 de la moitié supérieure de l'écran. L'effet d'exemple est le suivant.
En utilisation réelle, vous pouvez utiliser divers outils de sélection tels que des rectangles, des triangles, des pinceaux et des lassos pour sélectionner les positions correspondantes sur le masque.

Effet de découpe par texture 2D
Découpe par géométrie 3D
Utilisez la worldToLocalMatrix de la géométrie comme matrice inverse de sélection, combinez l'union (normal) et la différence (erase) via operation, et implémentez la sélection inversée via une entrée avec mode = SelectMode.invert.
public void on3DClip()
{
List<Data3D> _3Ds = new List<Data3D>();
var _mat1 = m_Box1.transform.worldToLocalMatrix;
var _mat2 = m_Box2.transform.worldToLocalMatrix;
var _mat3 = m_Box3.transform.worldToLocalMatrix;
var _mat4 = m_Clipsphere.transform.worldToLocalMatrix;
// Sélection par boîte
Data3D _3d01 = new Data3D();
_3d01.type = ShapeType.box;
_3d01.operation = OperationMode.normal;
_3d01.mode = SelectMode.normal;
_3d01.invMat = _mat1;
_3Ds.Add(_3d01);
Data3D _3d02 = new Data3D();
_3d02.type = ShapeType.box;
_3d02.operation = OperationMode.normal;
_3d02.mode = SelectMode.normal;
_3d02.invMat = _mat2;
_3Ds.Add(_3d02);
// Sélection par sphère
Data3D _3d04 = new Data3D();
_3d04.type = ShapeType.sphere;
_3d04.operation = OperationMode.normal;
_3d04.mode = SelectMode.normal;
_3d04.invMat = _mat4;
_3Ds.Add(_3d04);
// Effacer boîte/sphère (différence)
Data3D _3d03 = new Data3D();
_3d03.type = ShapeType.box;
_3d03.operation = OperationMode.erase;
_3d03.mode = SelectMode.normal;
_3d03.invMat = _mat3;
_3Ds.Add(_3d03);
// Inverser
//Data3D _3d05 = new Data3D();
//_3d05.mode = SelectMode.invert;
//_3Ds.Add(_3d05);
m_manager.SetClip(_3Ds);
}
Explication du code : 4 géométries sont utilisées, où Box1, Box2 et Sphere sont des sélections normales, et Box3 est une sélection d'effacement, c'est-à-dire l'effacement de la zone précédemment sélectionnée. Avec le code lié à l'inversion commenté, l'effet d'exemple est le suivant :

Effet de découpe par géométrie 3D
Décommentez le code d'inversion pour que l'inversion prenne effet ; l'effet d'exemple est le suivant. Invert inverse la zone précédemment sélectionnée ; c'est une commande et n'a pas besoin d'être associée à des données d'opération.
Notez en particulier que la liste est ordonnée ; différentes étapes d'opération produisent des effets finaux différents.

Effet de découpe géométrie 3D + inversion
Découpe en mode mixte
Mélangez des entrées de texture 2D et de géométrie 3D dans la même liste ; chaque entrée spécifie sa méthode de traitement via editType.
public void onMixClip()
{
// --- Préparation de la sélection 2D ---
// La taille de la texture est fixée à 1024*1024 ; gardez les autres propriétés identiques à l'exemple
Texture2D _texture = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture.filterMode = FilterMode.Point;
_texture.wrapMode = TextureWrapMode.Clamp;
int _count = 1024 * 1024;
int _half = _count / 2;
byte[] _values = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i < _half)
_values[i] = 128; // 128 signifie défaut, 240 signifie sélectionné, 0 signifie découpe
else
_values[i] = 0;
}
_texture.SetPixelData(_values, 0);
List<DataMix> _Mixs = new List<DataMix>();
DataMix _mix01 = new DataMix();
_mix01.editType = EditType.Edit2D;
_mix01.mv = m_camera.worldToCameraMatrix;
_mix01.texture = _texture;
_mix01.mode = SelectMode.normal;
_mix01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_Mixs.Add(_mix01);
// --- Préparation de la sélection 3D ---
var _mat1 = m_Box1.transform.worldToLocalMatrix;
var _mat2 = m_Box2.transform.worldToLocalMatrix;
var _mat3 = m_Box3.transform.worldToLocalMatrix;
var _mat4 = m_Clipsphere.transform.worldToLocalMatrix;
// Sélection par boîte
DataMix _mix02 = new DataMix();
_mix02.editType = EditType.Edit3D;
_mix02.type = ShapeType.box;
_mix02.operation = OperationMode.normal;
_mix02.mode = SelectMode.normal;
_mix02.invMat = _mat1;
_Mixs.Add(_mix02);
DataMix _mix03 = new DataMix();
_mix03.editType = EditType.Edit3D;
_mix03.type = ShapeType.box;
_mix03.operation = OperationMode.normal;
_mix03.mode = SelectMode.normal;
_mix03.invMat = _mat2;
_Mixs.Add(_mix03);
// Sélection par sphère
DataMix _mix04 = new DataMix();
_mix04.editType = EditType.Edit3D;
_mix04.type = ShapeType.sphere;
_mix04.operation = OperationMode.normal;
_mix04.mode = SelectMode.normal;
_mix04.invMat = _mat4;
_Mixs.Add(_mix04);
// Effacer boîte/sphère (différence)
DataMix _mix05 = new DataMix();
_mix05.editType = EditType.Edit3D;
_mix05.type = ShapeType.box;
_mix05.operation = OperationMode.erase;
_mix05.mode = SelectMode.normal;
_mix05.invMat = _mat3;
_Mixs.Add(_mix05);
// Inverser (activer selon les besoins)
DataMix _mix06 = new DataMix();
_mix06.editType = EditType.Edit3D;
_mix06.type = ShapeType.box;
_mix06.mode = SelectMode.invert;
//_Mixs.Add(_mix06);
m_manager.SetClip(_Mixs);
}
Explication du code : 4 géométries et 1 texture 2D sont utilisées, permettant un traitement mixte 2D et 3D. L'effet d'exemple est le suivant :

Effet de découpe en mode mixte
Étape 8 : Sortir de la découpe
Appelez QuitClipMode() pour effacer la découpe actuelle et restaurer l'affichage complet de la scène.
public void onClearClip()
{
m_manager.QuitClipMode();
}
Étapes clés
Les étapes clés pour effectuer une découpe en temps réel sur une scène 3DGS :
- Appelez
SetEditorMode(true)avant de charger les données pour entrer dans l'état d'édition. - Appelez
SetClipaprès la fin du chargement des données (après le déclenchement du callbackonLoadCallback, ou déclenché via un bouton/événement). - Choisissez la texture 2D, la géométrie 3D ou le mode mixte selon les besoins, et assurez-vous que l'ordre d'ajout de la liste de sélection correspond à votre attente.
- La texture de masque 2D est fixée à 1024 × 1024,
R8monocanal ; remplissez les valeurs de pixel selon la convention (128défaut conserver,0découpe). - Lors de l'effacement ou du changement de découpe, appelez d'abord
QuitClipMode().