Export GLTF/STL respecting ClippingPlanes?

Hi there, is there any way to export GLTFs and STLs but with Clipping Planes?

i currently export Meshes like so.

        scene.meshes
          .filter(mesh => (filterMeshes ? filterMeshes(mesh) : true))
          .forEach((mesh, index) => {
            const clonedMesh = (mesh as Mesh).clone().makeGeometryUnique()
            clonedMesh.bakeCurrentTransformIntoVertices()
            new Mesh(`${index}_mesh`, exportScene, rootMeshExporScene, clonedMesh)
            clonedMesh.dispose()
          })

since i have only 3 (merged) meshes consisting for hundreds of individual submeshes to reduce drawcalls i cannot filter individual meshes - so i thought there might be an easy way to respect clipping planes when exporting?

Cheers and thanks!

glTFs and STLs don’t support clipping planes information in their file format.

Maybe you can try to build a bounding volume with the clipping planes and apply a CSG operation to keep only what is inside… but I wouldn’t bet my life that it will work :slight_smile:

2 Likes

Hi,
i will give it a try… currently i do it like that:

const ClippingPlaneHeight = -50
let bufferData = mesh.getVerticesData(VertexBuffer.PositionKind)
let indices = mesh.getIndices() as Array<number>

if (bufferData && indices) {
    const cleanedIndices = indices.filter(
      index => bufferData![index * 3 + 1] > ClippingPlaneHeight
    )
clonedMesh.updateIndices(cleanedIndices)

wich does filter the unwanted faces out (in this case below the ClipplingPlaneHeight) - but when i export a gltf it still uses all positions to get the boundingBox to display the gltf…

is there any function to clean up position vertex data?

Cheers and thanks!

I don’t think there’s a function that would remove the vertices not referenced by the index array… You will have to write it yourself (this function will also have to clean the uvs, normals, etc).

Also, I guess you know it, but your clipping code will work only if a face is completely above or below the clipping plane, if some points are above and others are below it will fail.

Hmm… ok thanks i’ll try that.

i my case i have objects somewhere y<10000 and some ~0 so a rough filter is ok for me.

EDIT: shouldn’t this already do the trick? (it doesnt, but i cannot figure out the problem :confused: )

let bufferData = mesh.getVerticesData(VertexBuffer.PositionKind) as Array<number>
let indices = mesh.getIndices() as Array<number>
const cleanBufferData = bufferData.filter((buffer, index) => indices.includes(index))
clonedMesh.updateIndices(cleanedIndices)

No, because when you remove a vertex you must update all indices that are pointing after this vertex.

For eg, if indices = 0,4,2,3,1,5 and you remove vertex #2, indices become 0,3,2,1,4 and not 0,4,3,1,5 => indices 3,4,5 must be decremented by 1 to account for the vertex we just removed.

Oh no! you are right!
thanks - i will see what i can do

EDIT:
does that make more sense? - its still not doing the trick - the exported still seems to contain information about the not shown vertices

            if (positionData && indices) {
              // filter out wrong indices
              const cleanedIndices = indices.filter(
                index => positionData[index * 3 + 1] > ClippingPlaneHeight
              )
              clonedMesh.updateIndices(cleanedIndices)

              //generate a new position buffer array
              const cleanPositionBufferData: number[] = []
              cleanedIndices.forEach(index => {
                cleanPositionBufferData.push(
                  ...[
                    positionData[index * 3],
                    positionData[index * 3 + 1],
                    positionData[index * 3 + 2],
                  ]
                )
              })

              clonedMesh.updateVerticesData('PositionsKind', cleanPositionBufferData)
            }

Ok, … i am cheating a little - the mesh is disposed afterwards anyways:

              if (positionData && indices) {
              // filter out wrong indices
              const cleanedIndices = indices.filter(index => {
                const aboveGround = positionData[index * 3 + 1] > ClippingPlaneHeight
                if (!aboveGround) {
                  positionData[index * 3 + 1] = 0
                }
                return aboveGround
              })
              clonedMesh.updateIndices(cleanedIndices)
              clonedMesh.updateVerticesData('PositionsKind', positionData)
            }

so i am just resetting the y to 0 for the ones i am filtering…

1 Like