Guía de desarrollo de recorte en tiempo real
El LCC Unity SDK admite operaciones de edición como el resaltado y el recorte en escenas 3DGS. Esta guía presenta las operaciones de recorte en tiempo real: seleccionar un área mediante texturas proyectadas 2D, geometría 3D o una mezcla de ambas, recortando el área seleccionada fuera de la escena, con compatibilidad para la selección normal y la selección invertida.
Nota:
La función de recorte actual es solo un efecto de visualización en tiempo de ejecución; no modifica el archivo de datos original de ninguna manera y no admite guardar ni exportar el resultado de la edición. Si necesitas ajustar el color, recortar y guardar datos, usa la herramienta de software XGRIDS LCC Editor.
Si no quieres modificar los datos, también puedes registrar las operaciones y reproducirlas después de que los datos terminen de cargarse la próxima vez.
Requisitos previos
Recortar una escena a través del SDK requiere las siguientes condiciones:
- Entrar en el estado de edición antes de cargar los datos. El SDK está en el estado de navegación (View) por defecto, que proporciona el mejor rendimiento y se recomienda para la navegación normal. Para realizar operaciones de edición como el recorte, cambia al estado de edición mediante
SetEditorMode(true)antes de llamar aLoad. Este método solo surte efecto si se llama antes de cargar todos los datos. - Realizar la operación de recorte después de que los datos terminen de cargarse. La interfaz de recorte debe llamarse después de que los datos de la escena se hayan cargado por completo.
Paso 1: Configurar la escena
Prepara los GameObjects necesarios para el recorte en la escena como se muestra a continuación.

Estructura de jerarquía de la escena para el ejemplo de recorte
- Main Camera: la cámara de la escena; el recorte 2D usa sus matrices de vista y proyección.
- LCCManager: un GameObject vacío con un Transform normalizado, con el script
LCCManagerañadido. - LCCRenderer: un GameObject vacío con el Transform establecido como Rotation.x = -90, Scale.x = -1 (alineado con el sistema de coordenadas de los datos LCC), usado para adjuntar el script
Clipescrito más adelante. - Geometría de selección 3D: objetos auxiliares para el recorte 3D. El ejemplo prepara 3 Cubes (
Box1,Box2,Box3) y 1 Sphere (Clipsphere); mover y escalar estos objetos controla la posición y el tamaño de la selección de recorte.
Nota:
Para los ajustes relacionados con los GameObjects de la cámara de renderizado, LCCManager y LCCRenderer, consulta las secciones relevantes de Guía de inicio rápido para PC y Guía de optimización de ajustes del proyecto.

Geometría de selección usada para el recorte 3D (Box1 / Box2 / Box3 / Clipsphere)
Paso 2: Comprender las estructuras de datos
El recorte implica tres métodos de operación — 2D, 3D y mixto 2D/3D. Los enums y structs usados son los siguientes.
public enum SelectMode { normal, invert, clip } // selección normal, inversión, recorte en tiempo real
public enum OperationMode { normal, erase } // selección normal, borrar selección
public enum ShapeType { box, sphere } // selección 3D Box, selección 3D Sphere
public enum EditType { Edit2D, Edit3D } // edición 2D, edición 3D
// Selección por textura 2D
public struct Data2D
{
public Texture2D texture; // textura de máscara 2D
public Matrix4x4 mv; // matriz de vista de la cámara
public Matrix4x4 mvp; // matriz de vista-proyección de la cámara
public SelectMode mode; // modo de selección
}
// Selección por geometría 3D
public struct Data3D
{
public ShapeType type; // tipo de geometría (box / sphere)
public Matrix4x4 invMat; // matriz inversa mundo-a-local de la geometría
public OperationMode operation; // tipo de operación (unión normal / diferencia de borrado)
public SelectMode mode; // modo de selección
}
// Selección mixta 2D / 3D
public struct DataMix
{
public EditType editType; // tipo de edición (obligatorio; determina si se usan los campos 2D o 3D)
public Texture2D texture; // textura de máscara 2D (usada por Edit2D)
public Matrix4x4 mv; // matriz de vista de la cámara (usada por Edit2D)
public Matrix4x4 mvp; // matriz de vista-proyección de la cámara (usada por Edit2D)
public ShapeType type; // tipo de geometría (usado por Edit3D)
public Matrix4x4 invMat; // matriz inversa de la geometría (usada por Edit3D)
public OperationMode operation; // tipo de operación (usado por Edit3D)
public SelectMode mode; // modo de selección (obligatorio)
}
Hay tres puntos a tener en cuenta sobre la lista de selección:
- La lista está ordenada. Ya sea 2D o 3D, las entradas de la lista surten efecto en orden; asegúrate de que el orden de adición coincide con tu expectativa.
- Invertir es un comando de operación y no necesita asociarse con datos de selección específicos. Simplemente añade una entrada con
mode = SelectMode.invertpara invertir el área seleccionada actualmente. - El número máximo de entradas en una sola lista es 255. Superarlo devuelve un código de error.
Paso 3: Comprender las API de recorte
Todas las interfaces relacionadas con el recorte las proporciona LCCManager, incluidas tres sobrecargas de SetClip y un método de salida.
SetClip (recorte por textura 2D)
// Valor de retorno: int
// 0: éxito
// 1: la lista es null o tiene 0 elementos
// 2: los elementos de la lista superan el máximo de 255
public int SetClip(List<Data2D> _2Ds)
Recorta la escena usando una máscara de textura proyectada 2D; el área marcada se recorta fuera de la escena.
SetClip (recorte por geometría 3D)
// Valor de retorno: int
// 0: éxito
// 1: la lista es null o tiene 0 elementos
// 2: los elementos de la lista superan el máximo de 255
// 3: el número de cajas de geometría de selección es 0
public int SetClip(List<Data3D> _3Ds)
Define el área de recorte usando geometría 3D (cuboide, cubo, esfera), admitiendo combinaciones de unión y diferencia. Se requiere al menos una geometría con operation == OperationMode.normal.
SetClip (recorte en modo mixto)
// Valor de retorno: int
// 0: éxito
// 1: la lista es null o tiene 0 elementos
// 2: los elementos de la lista superan el máximo de 255
public int SetClip(List<DataMix> _Mix)
Define el área de recorte usando texturas 2D y geometría 3D al mismo tiempo; cada entrada determina si se procesa como 2D o 3D mediante editType.
QuitClipMode
// Valor de retorno: void
public void QuitClipMode()
Sale del modo de recorte y restaura la visualización completa de la escena.
Consejo:
Las tres sobrecargas de
SetClipson mutuamente excluyentes. Al cambiar de método de recorte o limpiar el recorte actual, llama primero aQuitClipMode()y luego establece el nuevo recorte.
Paso 4: Especificación de la textura de máscara 2D
El recorte 2D describe la selección mediante una textura de máscara, admitiendo varios métodos de selección como cuadriláteros, triángulos, pinceles y lazos — simplemente marca los píxeles correspondientes en la textura con el valor de recorte. Al usar operaciones 2D, la cámara debe estar bloqueada y la textura marcada desde un punto de vista fijo. La textura y los valores de píxel tienen las siguientes convenciones:
- La textura está fijada en 1024 × 1024,
R8de un solo canal, sin Mipmap, con filtrado por puntos (FilterMode.Point) y muestreo limitado (TextureWrapMode.Clamp). - Convenciones de valor de píxel:
| Valor de píxel | Significado |
|---|---|
128 | Por defecto (mantener) |
240 | Seleccionado |
180 | Deseleccionar (borrar el área ya seleccionada) |
0 | Recorte |
En un escenario de recorte, normalmente solo se usan los dos valores 128 (mantener por defecto) y 0 (recorte).
Paso 5: Escribir el script
Crea un nuevo script C# llamado Clip.cs. Primero completa el esqueleto básico: en Start, entra en el estado de edición y carga los datos; después de que la carga finalice, establece el indicador de carga para que los métodos de recorte posteriores lo comprueben.
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);
// Entra en el modo de edición; debe llamarse antes de Load
m_manager.SetEditorMode(true);
m_renderer = m_manager.GetRender(this.transform);
if (m_renderer == null)
Debug.LogError("Error en GetRender, comprueba que el manager esté configurado correctamente y que la ruta del archivo sea válida.");
m_renderer.Load(m_FilePath, onLoadProgress, onLoadCallback);
}
private void onLoadProgress(float value)
{
Debug.Log($"progreso de carga: {value}");
}
private void onLoadCallback()
{
Debug.Log("datos cargados !!!");
m_isLoaded = true;
// Desactiva el renderizado del entorno (nube de puntos de campo lejano de baja precisión) para observar mejor el resultado del recorte
m_renderer.SetEnvironment(false);
}
// métodos de recorte 2D / 3D / mixto a continuación
}
Nota:
SetEditorMode(true)debe llamarse antes deLoadpara surtir efecto; ySetClipdebe llamarse después de que los datos terminen de cargarse (después de que se dispare la devolución de llamadaonLoadCallback).SetEnvironment(false)desactiva la nube de puntos del entorno de campo lejano para que el resultado del recorte sea más claro; decide si llamarla según sea necesario.
Paso 6: Adjuntar el script y establecer propiedades
- Adjunta el script
Clip.csal GameObject LCCRenderer. - En la ventana Inspector, arrastra el GameObject LCCManager a la propiedad Manager del script.
- Rellena la ruta del archivo LCC en la propiedad File Path.
- Arrastra
Box1,Box2,Box3yClipspherede la escena a las propiedades correspondientes del script respectivamente.

Establecer las propiedades del script Clip en el Inspector
Paso 7: Ejemplos de operación de recorte
Añade los métodos siguientes a la clase Clip y llama al método correspondiente después de ejecutar y después de que los datos terminen de cargarse.
Recorte por textura 2D
Construye dos texturas de máscara R8, marca los píxeles a recortar como 0 y el resto del área a mantener como 128, luego construye Data2D con las matrices de la cámara y añádelos a la lista.
public void on2DClip()
{
// El tamaño de la textura está fijado en 1024*1024; mantén las demás propiedades igual que el ejemplo
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 significa recorte, 128 significa por defecto, 240 significa seleccionado
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);
}
Explicación del código: se construyen dos texturas de máscara. La primera máscara recorta la mitad inferior de la pantalla (el origen de la pantalla es la esquina inferior izquierda), y la segunda máscara recorta la región de 0.75 a 0.9 de la mitad superior de la pantalla. El efecto del ejemplo es el siguiente.
En el uso real, puedes usar varias herramientas de selección como rectángulos, triángulos, pinceles y lazos para seleccionar las posiciones correspondientes en la máscara.

Efecto de recorte por textura 2D
Recorte por geometría 3D
Usa el worldToLocalMatrix de la geometría como matriz inversa de selección, combina unión (normal) y diferencia (erase) mediante operation, e implementa la selección invertida mediante una entrada con 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;
// Selección de caja
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);
// Selección de esfera
Data3D _3d04 = new Data3D();
_3d04.type = ShapeType.sphere;
_3d04.operation = OperationMode.normal;
_3d04.mode = SelectMode.normal;
_3d04.invMat = _mat4;
_3Ds.Add(_3d04);
// Borrar caja/esfera (diferencia)
Data3D _3d03 = new Data3D();
_3d03.type = ShapeType.box;
_3d03.operation = OperationMode.erase;
_3d03.mode = SelectMode.normal;
_3d03.invMat = _mat3;
_3Ds.Add(_3d03);
// Invertir
//Data3D _3d05 = new Data3D();
//_3d05.mode = SelectMode.invert;
//_3Ds.Add(_3d05);
m_manager.SetClip(_3Ds);
}
Explicación del código: se usan 4 geometrías, donde Box1, Box2 y Sphere son selecciones normales, y Box3 es una selección de borrado, es decir, borrar el área seleccionada previamente. Con el código relacionado con la inversión comentado, el efecto del ejemplo es el siguiente:

Efecto de recorte por geometría 3D
Descomenta el código de inversión para que la inversión surta efecto; el efecto del ejemplo es el siguiente. La inversión invierte el área seleccionada previamente; es un comando y no necesita asociarse con datos de operación.
En particular, ten en cuenta que la lista está ordenada; diferentes pasos de operación producen diferentes efectos finales.

Efecto de recorte por geometría 3D + inversión
Recorte en modo mixto
Mezcla entradas de textura 2D y geometría 3D en la misma lista; cada entrada especifica su método de procesamiento mediante editType.
public void onMixClip()
{
// --- Preparación de la selección 2D ---
// El tamaño de la textura está fijado en 1024*1024; mantén las demás propiedades igual que el ejemplo
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 significa por defecto, 240 significa seleccionado, 0 significa recorte
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);
// --- Preparación de la selección 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;
// Selección de caja
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);
// Selección de esfera
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);
// Borrar caja/esfera (diferencia)
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);
// Invertir (habilítalo según sea necesario)
DataMix _mix06 = new DataMix();
_mix06.editType = EditType.Edit3D;
_mix06.type = ShapeType.box;
_mix06.mode = SelectMode.invert;
//_Mixs.Add(_mix06);
m_manager.SetClip(_Mixs);
}
Explicación del código: se usan 4 geometrías y 1 textura 2D, permitiendo el procesamiento mixto 2D y 3D. El efecto del ejemplo es el siguiente:

Efecto de recorte en modo mixto
Paso 8: Salir del recorte
Llama a QuitClipMode() para limpiar el recorte actual y restaurar la visualización completa de la escena.
public void onClearClip()
{
m_manager.QuitClipMode();
}
Pasos clave
Los pasos clave para realizar recortes en tiempo real en una escena 3DGS:
- Llama a
SetEditorMode(true)antes de cargar los datos para entrar en el estado de edición. - Llama a
SetClipdespués de que los datos terminen de cargarse (después de que se dispare la devolución de llamadaonLoadCallback, o se active mediante un botón/evento). - Elige textura 2D, geometría 3D o modo mixto según sea necesario, y asegúrate de que el orden de adición de la lista de selección coincide con tu expectativa.
- La textura de máscara 2D está fijada en 1024 × 1024,
R8de un solo canal; rellena los valores de píxel según la convención (128mantener por defecto,0recorte). - Al limpiar o cambiar de recorte, llama primero a
QuitClipMode().