How to get started with VRMLLoader?

Hi there,

I am totally new to Three.js and need to implement a viewer component for VRML 2.0 models in a React front end app.
What is the minimal code to load a VRML file and display an interactive viewer like in three.js webgl - loaders - VRML loader?

I have seen this PR by @Mugen87, but I am unsure which parts from VRMLLoader are actually an integral part of the Three.js package and which parts I would have to write myself. In the (official documentation)[three.js docs] I cannot find the VRMLLoader mentioned. Also, is Chevrotain still needed as a dependency?

I would be ever so grateful for a short “Getting Started” and some code snippet.

I think the example shows more or less the minimal code which is necessary.

So you’re saying I should use my F12 browser debugging tools and check the website’s actual source code?
Or did I miss some sort of “Show Code” button on said site?

Correct. You can also use the below URL and click on the button at the bottom right.

https://threejs.org/examples/#webgl_loader_vrml

1 Like

Ok thank you very much.

Just to clarify further: I would have to copy all the files in the folder ./jsm and paste it in my app’s directory, right? These are the parts that do not come with an npm install three. Is that correct?

And the lil-gui is just needed for the floating control box? I assume I would not need that just for the VRML rendering?

All JS files in the jsm directory are part of the three npm package. You don’t need to copy them.

Yes, lil-gui is only used for the GUI.

Great. Thanks for all your help and your on-going work on this loader. This ancient file format is still relevant in the domain of particle physics when exporting 3d models from CERN simulation software.

1 Like

@Mugen87 after a longer break, I came back to my Three.js project. I did a npm install three and managed to render a rotating cube in my application. However, I can neither find VRMLLoader nor OrbitControls anywhere in my node_modules.

What am I missing? How can I import said data types?

Have you already checked out how both modules are imported in the VRML example? You probably need the missing import map with the latest version.

Thanks for the hint. Yes, I did check the example. However, I must have ignored/dismissed the import map part for two reasons:

  1. My project is created with Create React App and Typescript, so I kind of ignored the <script>-Tags boilerplate.
  2. I haven’t heard of the import map concept before. I’ve always just used ES6 modules.

My code so far looks like this:

import { useEffect, useRef } from "react"
import * as THREE from "three"

function resizeCanvasToDisplaySize(camera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, forceResize?: boolean): boolean {
  if (forceResize === undefined)
    forceResize = false

  const canvas = renderer.domElement
  const pixelRatio = window.devicePixelRatio | 0
  const displayWidth = canvas.clientWidth * pixelRatio
  const displayHeight = canvas.clientHeight * pixelRatio
  const needsResize = canvas.width !== displayWidth || canvas.height !== displayHeight
  if (needsResize || forceResize) {
    renderer.setSize(displayWidth, displayHeight, false) // you must pass false here or three.js sadly fights the browser
    camera.aspect = displayWidth / displayHeight
    camera.updateProjectionMatrix()
  }
  return needsResize
}

function MyModelViewer() {
  const canvasRef = useRef<HTMLCanvasElement>(null)

  useEffect(() => {
    if (canvasRef && canvasRef.current) {
      const defaultAspect = 2
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, defaultAspect, 0.1, 1000) // A camera always looks down its local, negative z-axis
      camera.position.z = 5
      const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.current })

      const geometry = new THREE.BoxGeometry(1, 1, 1)
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
      const cube = new THREE.Mesh(geometry, material)
      scene.add(cube)

      // controls = new THREE.OrbitControls(camera, renderer.domElement);
      // controls.minDistance = 1;
      // controls.maxDistance = 200;
      // controls.enableDamping = true;

      const animate = () => {
        requestAnimationFrame(animate)
        resizeCanvasToDisplaySize(camera, renderer)
        updateScene()
        renderer.render(scene, camera)
      }

      const updateScene = () => {
        cube.rotation.x += 0.01
        cube.rotation.y += 0.01
      }

      resizeCanvasToDisplaySize(camera, renderer, true)
      animate()
    }
  }, [])
  // ############################
  return (
    <div className="container">
      <p className="title">Scene</p>
      <canvas ref={canvasRef} style={{ width: "1024px", height: "768px" }}></canvas>
    </div>
  )
}

export default MyModelViewer

How would I have to import the OrbitControls in this context? Do I have to add the import map to my static public/index.html? And if I do so, how would VSCode and Babel pick that up both for type checking and compilation?

Like I said, I am unfamiliar with import maps and my google research wrt import maps and create react app was not successful. I would appreciate any hint in the right direction.

The import map is not relevant if you use a bundler. The import of OrbitControls in your case should look like so:

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

That works. Awesome! I was missing the examples subdirectory in my import before. Thanks for the hint.

My VSCode search must be broken. I double-checked again: If I search the whole project workspace for OrbitControls, nothing is found.

Anyways, thank you so much for your help. I really appreciate your dedication and your quick response times in this forum. Keep up the great work! :+1:

1 Like