Mi biblioteca de juegos de código abierto contiene una implementación de malla de corte. Funciona con la API de Irrlicht, pero podría reescribirse para usar una API diferente con un esfuerzo modesto. Puede usar el código bajo los términos de la licencia BSD, o aprender de ello un implemento propio.
Ver MeshTools :: splitMeshZ en this file for an implementation of mesh slicing.
Si lo que desea es conocer el algoritmo, he aquí una descripción de alto nivel de lo que hice:
inicialmente pensé en el uso de un cuadro delimitador eje alineado para especificar dónde cortar la malla. Esto fue problemático porque introdujo muchos casos especiales. Por ejemplo, un borde que cruza la esquina de la caja se puede dividir en tres partes en lugar de solo dos.
El uso de un plano para cortar la malla en una malla izquierda y una malla derecha reduce el número de casos especiales, porque un borde está en un lado del plano o del otro, o cruza el plano y también lo está cortado en exactamente dos pedazos.
Cualquier configuración de cortes deseada se puede hacer simplemente cortando una vez, tomando una de las mallas resultantes y cortándola nuevamente en otra ubicación, y así sucesivamente. Específicamente en el caso que describa en la sección, se puede cortar un círculo de una esfera cortando la mitad de la esfera, moviendo el plano una pequeña cantidad y cortando la otra mitad dejando solo una banda delgada. (No se puede cortar una malla hasta literalmente sin profundidad con el código que escribí, pero se puede cortar una malla hasta lo que haya establecido como el umbral de igualdad de coma flotante. Creo que elegí arbitrariamente 0,001 en mi código).
Usando una lógica similar, cualquier ángulo deseado del plano de corte se puede lograr usando un plano fijo; solo necesita transformar la malla para rotarla en relación con el plano de corte fijo, y luego transformar el resultado. (Para mi juego, solo necesitaba cortes perpendiculares al plano XY, así que para simplificar solo permito que se establezca el valor Z del corte, y supongo que el corte está en esa ubicación Z.)
OK, ahora que hemos simplificado el problema, el algoritmo no es tan malo:
condición de inicio: Usted tiene un plano de corte. Tienes un conjunto de triángulos fuente. Tiene dos conjuntos de destino de polígonos (no triángulos; los cuatriciclos se pueden generar cortando el triángulo). Los dos conjuntos de destinos se llaman Izquierda y Derecha.
Proceso: Iterar más de tres puntos de un triángulo. Cuente el número de puntos que son menores que el plano de corte. Llamaré a esos menos que el plano de corte a la izquierda y los que son mayores que el plano de corte a la derecha. Hay sólo un puñado de casos:
- Todos los puntos del triángulo están a la izquierda: poner el triángulo en el conjunto izquierdo
- Todos los puntos están a la derecha: poner el triángulo de la derecha conjunto
- Uno el punto está a la izquierda, otros están a la derecha: si cortas un triángulo a través de dos bordes y sostienes uno de los puntos, terminas sosteniendo un triángulo más pequeño. Ponga un triángulo en el conjunto izquierdo formado por el punto izquierdo, y los dos puntos donde los bordes cruzan el plano. Coloque un quad en el conjunto de la derecha (vea el siguiente caso).
Dos puntos quedan, un punto es el correcto. Si está sosteniendo un borde de un triángulo y lo corta a través de los otros dos bordes, se queda sosteniendo un trapezoide. Coloque un quad en el conjunto izquierdo compuesto por los dos puntos en su mano, más los dos puntos que cruzan el corte. Coloque un triángulo en el conjunto de la derecha (imagen de espejo del caso anterior).
Cuando termine, convierta los quads en triángulos agregando un enlace en la parte más corta.
Eso es todo. Ese es el algoritmo básico. El código real maneja algunos casos más, como qué pasa si un borde es exactamente igual al corte, qué pasa si un triángulo está exactamente en el borde, no agrega polígonos degenerados (por ejemplo, un punto sin cuerpo), etc.
Misc. temas (todos los cubiertos en el código relacionado):
No complicar los cálculos por LERP'ing el punto donde cruza el borde del plano de corte. No necesita una interpolación lineal completa, en realidad es High School secundaria Álgebra II: aumentar sobre la carrera, multiplicada por
Es ventajoso guardar en caché los puntos generados (LERP) para que los triángulos que comparten vértices en la malla sin cortar compartirá los nuevos vértices correspondientes en la malla de corte.
Si va a conservar el uso compartido de vértices, y está utilizando los búferes de índice triangular, desafortunadamente aún no conoce el índice cuando genera las formas para colocarlas en los conjuntos izquierdo y derecho. Utilizo una clase llamada "PossibleVertex" para representar un número de índice triangular futuro.
Si va a mostrar la malla, el orden de la bobina es importante. Una cuidadosa reflexión sobre cómo codificarlo puede garantizar que los polígonos resultantes usen el mismo orden de devanado que los triángulos de los que provienen. Esto se vuelve especialmente complicado cuando se triangulan los cuádriceps. No puedo recordar los detalles, pero todo se maneja en el código vinculado.
Para mi juego, quería hacer una cinta plana que conectara dos mallas cortadas. Es por eso que splitMeshZ resulta en 3 mallas, en lugar de solo dos.Puedes usar la malla del medio o simplemente ignorarla.
Una posibilidad sería la de hacer que la malla con OpenGL, y utilizar un plano de recorte para hacer el "slicing". –