twgl.js icon indicating copy to clipboard operation
twgl.js copied to clipboard

How to import files from Blender?

Open munrocket opened this issue 6 years ago • 3 comments

For example I have an object in Blender and I can export files with glTF, OBJ, COLLADA etc. I don't want to use Three.js because it's too heavy for this purpose.

munrocket avatar Jun 06 '19 10:06 munrocket

importing gLTF etc files is way beyond the scope of twgl. To import gLTF or COLLADA you need a scenegraph, you need materials, you need a shader generator, you need lights, cameras. If you really want that you'll need to write a ton of code and keep all kinds of state so really anything that could load those files should be some other library. Sure it might be based on twgl or not but twgl is not the place for high level stuff like that

There is some code here that partially loads a gLTF file and uses twgl to draw. For the most part it ignores materials and it certainly ignores animation and cameras.

There's also some code here for parsing a .obj file. I don't even remember why I wrote it or what state it's in. You can of course look through the three.js code for other examples of parsing various files.

greggman avatar Jun 06 '19 16:06 greggman

I have really specific task without light and cameras. Also I don’t see any problem with custom shader. I just need to know vertex positions from blender :) Three.js much heavier than microframeworks and don’t fit to orthographic projection of bunch of triangles.

munrocket avatar Jun 06 '19 17:06 munrocket

You can export the model in .obj (wavefront obj) format and use ready-made solutions (webgl-obj-loader for example) for parsing these files or you can parse the file yourself. For example, I'm parsing the file myself because I only need the vertex and faces

const uv4 = [[0, 0], [1, 0], [1, 1], [0, 1]]
export function getVBForVSTFromObj(obj) {
  const preLines = obj.split(/[\r\n]/).filter(s => s.length)

  const exNs = (a, fchar) =>
    a
      .filter(s => s[0] === fchar)
      .map(s =>
        s
          .split(' ')
          .filter(s => s.length)
          .slice(1)
          .map(Number)
      )

  const exFs = s =>
    s
      .filter(s => s[0] === 'f')
      .map(s =>
        s
          .split(/\s+/)
          .filter(s => s.length)
          .slice(1)
          .map(s => s.split('/').map(Number))
      )

  const vertexList = exNs(preLines, 'v')
  const faceList = exFs(preLines)

  const filteredFaceList = faceList.filter(is => is.length === 4)
  const vertexes = filteredFaceList
    .map(is => {
      const [v0, v1, v2, v3] = is.map(i => vertexList[i[0] - 1])
      return [[v0, v1, v2], [v0, v2, v3]]
    })
    .flat(4)

  const textureCoords = Array.from({ length: filteredFaceList.length }, () => [
    [uv4[0], uv4[1], uv4[2]],
    [uv4[0], uv4[2], uv4[3]],
  ]).flat(4)

  return [vertexes, textureCoords]
}

dimensi avatar Nov 07 '19 16:11 dimensi