csgToGeometries = (csgs, options) => {
  const defaults = {
    smoothLighting: false, // set to true if we want to use interpolated vertex normals this creates nice round spheres but does not represent the shape of the actual model
    normalThreshold: 0.349066, // 20 deg
    faceColor: [1, 0.4, 0, 1]// default color
  }
  const { smoothLighting, normalThreshold, faceColor } = Object.assign({}, defaults, options)
  const faceColorRgb = faceColor === undefined ? undefined : normalizedColor(faceColor) // TODO : detect if hex or rgba

  const convert = (csg) => {
    const geometries = []

    const positions = []
    const colors = []
    const normals = []
    const indices = []

    // flag for transparency
    let isTransparent = false

    const polygons = csg.canonicalized().toPolygons()

    /* let positions = new Float32Array(faces * 3 * 3)
    let normals = new Float32Array(faces * 3 * 3) */

    let normalPositionLookup = []
    normalPositionLookup = {}
    let tupplesIndex = 0

    for (let i = 0; i < polygons.length; i++) {
      const polygon = polygons[i]

      const color = polygonColor(polygon, faceColorRgb)
      const rawNormal = polygon.plane.normal
      const normal = [rawNormal.x, rawNormal.y, rawNormal.z]

      if (color[3] !== 1) {
        isTransparent = true
      }

      const polygonIndices = []
      // we need unique tupples of normal + position , that gives us a specific index (indices)
      // if the angle between a given normal and another normal is less than X they are considered the same
      for (let j = 0; j < polygon.vertices.length; j++) {
        let index

        const vertex = polygon.vertices[j]
        const position = [vertex.pos.x, vertex.pos.y, vertex.pos.z]

        if (smoothLighting) {
          const candidateTupple = { normal, position }
          const existingTupple = fuzyNormalAndPositionLookup(normalPositionLookup, candidateTupple, normalThreshold)
          if (!existingTupple) {
            const existingPositing = normalPositionLookup[candidateTupple.position]
            const itemToAdd = [{ normal: candidateTupple.normal, index: tupplesIndex }]
            if (!existingPositing) {
              normalPositionLookup[candidateTupple.position] = itemToAdd
            } else {
              normalPositionLookup[candidateTupple.position] = normalPositionLookup[candidateTupple.position]
                .concat(itemToAdd)
            }
            index = tupplesIndex
            // normalPositionLookup.push(candidateTupple)
            // index = normalPositionLookup.length - 1
            if (faceColor !== undefined) {
              colors.push(color)
            }
            normals.push(normal)
            positions.push(position)
            tupplesIndex += 1
          } else {
            index = existingTupple.index
          }
        } else {
          if (faceColor !== undefined) {
            colors.push(color)
          }
          normals.push(normal)
          positions.push(position)
          index = positions.length - 1
        }

        // let prevcolor = colors[index]
        polygonIndices.push(index)
      }

      for (let j = 2; j < polygonIndices.length; j++) {
        indices.push([polygonIndices[0], polygonIndices[j - 1], polygonIndices[j]])
      }

      // if too many vertices or we are at the end, start a new geometry
      if (positions.length > 65000 || i === polygons.length - 1) {
        // special case to deal with face color SPECICIALLY SET TO UNDEFINED
        if (faceColor === undefined) {
          geometries.push({
            indices,
            positions,
            normals,
            isTransparent
          })
        } else {
          geometries.push({
            indices,
            positions,
            normals,
            colors,
            isTransparent
          })
        }
      }
    }
    return geometries
  }

  csgs = toArray(csgs)
  const geometriesPerCsg = csgs.map(convert)

  return geometriesPerCsg
}
convert a CSG from csg.js to an array of geometries with positions, normals, colors & indices
typically used for example to display the csg data in a webgl wiever
@param {Array} csgs single or an array of CSG object
@param {Object} options options hash
@param {Boolean} options.smoothLighting=false set to true if we want to use interpolated vertex normals
this creates nice round spheres but does not represent the shape of the actual model
@param {Float} options.normalThreshold=0.349066 threshold beyond which to split normals // 20 deg
@param {String} options.faceColor='#FF000' hex color
@returns {Object} {indices, positions, normals, colors}