node-3d / 3d-core-raub

An extensible Node.js 3D core for desktop applications
https://github.com/node-3d/node-3d
MIT License
72 stars 4 forks source link

How to use GLTFLoader? #21

Closed kevinJ045 closed 2 months ago

kevinJ045 commented 3 months ago

Whenever i try to load any gtlf file, it throws this:

TypeError: Failed to parse URL from /home/makano/workspace/prev3d/fairy_tail.glb
    at new Request (node:internal/deps/undici/undici:4855:19)
    at FileLoader.load (file:///home/makano/workspace/rew.three/node_modules/three/build/three.module.js:43866:15)
    ... 6 lines matching cause stack trace ...
    at exec (/home/makano/workspace/rew/lib/rew/cli/run.js:7:9)
    at runIt (/home/makano/workspace/rew/lib/rew/cli/run.js:20:19) {
  [cause]: TypeError: Invalid URL
      at new URL (node:internal/url:797:36)
      at new Request (node:internal/deps/undici/undici:4853:25)
      at FileLoader.load (file:///home/makano/workspace/rew.three/node_modules/three/build/three.module.js:43866:15)
      at GLTFLoader.load (file:///home/makano/workspace/rew.three/node_modules/three/examples/jsm/loaders/GLTFLoader.js:241:10)
      at Function.init3D (/home/makano/workspace/prev3d/main.coffee:25:16)
      at Function.main (/home/makano/workspace/prev3d/main.coffee:33:19)
      at doCode (/home/makano/workspace/rew/lib/rew/modules/runtime.js:64:21)
      at runPath (/home/makano/workspace/rew/lib/rew/modules/runtime.js:83:9)
      at module.exports.run (/home/makano/workspace/rew/lib/rew/main.js:4:9)
      at exec (/home/makano/workspace/rew/lib/rew/cli/run.js:7:9) {
    code: 'ERR_INVALID_URL',
    input: '/home/makano/workspace/prev3d/fairy_tail.glb'
  }
}
raub commented 2 months ago

Have you used addThreeHelpers(THREE, gl);?

kevinJ045 commented 1 month ago
import * as Three from 'three';
import { init, addThreeHelpers } from '3d-core-raub';

###*
 * @param options {TInitOpts}
*###
createDocument = (options) ->
  ctx = init(options);
  addThreeHelpers(Three, ctx.gl) if options.three isnt false
  return ctx

createScene = (ctx3d, options, useListener) ->
  target = emitter();
  ctx = if useListener then {
    ...target
  } else {
    listener: target
  };
  renderer = new Three.WebGLRenderer();
  renderer.setPixelRatio( ctx3d.doc.devicePixelRatio );
  renderer.setSize( ctx3d.doc.innerWidth, ctx3d.doc.innerHeight );

  ctx.renderer = renderer;

  ctx.camera = new Three.PerspectiveCamera(options.camera?.fov or 70, ctx3d.doc.innerWidth / ctx3d.doc.innerHeight, options.camera?.near or 1, options.camera?.far or 1000);
  ctx.camera.position.z = 2;

  ctx.scene = new Three.Scene();

  ctx.scene.addAt = ([x, y, z], mesh) ->
    ctx.scene.add mesh
    mesh.position.x = x
    mesh.position.y = y
    mesh.position.z = z

  ctx.animate = () ->
    time = Date.now();
    target.emit('animate:beforeFrameRender', time);
    ctx3d.requestAnimationFrame(ctx.animate);
    target.emit('animate:render', time);
    renderer.render(ctx.scene, ctx.camera);
    target.emit('animate:afterFrameRender', time);

  addSceneUtils(ctx3d, ctx);

  return ctx

customMesh = (ctx, scene, mesh) ->
  mesh.toScene = () ->
    scene.scene.add(this)
    return this
  return mesh

addSceneUtils = (ctx, scene) ->

  MESH_TYPES =
    box: ctx.BoxGeometry

  scene.mat = (options) ->
    if typeis(options, num) or typeis(options, str) then options = { color: options }
    return new ctx.MeshStandardMaterial options

  scene.mesh = (type, options) ->

    if type of MESH_TYPES then type = MESH_TYPES[type]
    return customMesh ctx, scene, new ctx.Mesh(new type(...options.size), options.material)

addUtils = (ctx) -> null

# import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' assert esm: true;

###*
 * @type {(options: TInitOpts) => void}
*###
createForge3d = (options = { isGles3: true }) ->
  documentContext = createDocument options
  documentContext.canvas.getRootNode = () -> documentContext.document
  context3d = {
    ...Three,
    ...documentContext,
    modules: []
  }
  context3d.Forge3D = context3d;
  context3d.__pathname = pjoin dirname(module.filepath), './node_modules/three'

  addUtils(context3d, options);
  context3d.Scene = Usage::create('scene3d', ((cb) -> cb.call(createScene(context3d, options, true))), false)
  context3d.Scene.prototype = {};
  context3d.Scene::create = () -> createScene(context3d, options)

  context3d.With = (...modules) ->
    for modpath in modules
      if typeof modpath is 'string'
        module = require pjoin("three/examples/jsm", (if modpath.endsWith '.js' then modpath else "#{modpath}.js")), true
        context3d.modules.push modpath
        mod = {...module}
        for i of mod
          if i is 'default' then i = basename modpath
          context3d[i] = mod[i]
      else if typeof modpath == 'object'
        for i of modpath
          context3d[i] = modpath[i]
    context3d

  context3d.Compose = (cb) ->
    if typeof cb == "function"
      namespace.group [context3d, cb], Use: () -> using namespace this
    else
      (cb2) -> Usage::group cb, cb2

  if Array.isArray options.with
    context3d.With options.with...
  context3d

Forge3D = Usage::create 'forge3d', (options, cb) ->
  if Array.isArray options
    options = { with: options, isGles3: true }
  if typeof options is "function" and not cb
    cb = options
    options = { isGles3: true }
  cb createForge3d options

Forge3D.Weld = (options = { isGles3: true }) -> createForge3d options

module.exports = Forge3D

Yes, it exists: addThreeHelpers(Three, ctx.gl) if options.three isnt false

kevinJ045 commented 1 month ago

Okay, i figured it out, it's from my own runtime