skip to Main Content

When attempting to use THREE.InfiniteGridHelper there doesn’t seem to be a way to import the code that doesn’t generate an error. Even copying and pasting the code does not work.

Currently I have the code copied and pasted into my main.js page and this gives the error it gives

Uncaught TypeError: "InfiniteGridHelper" is read-only
http://127.0.0.1:5000/static/main.js:10

I have also tried pasting the code into its own InfiniteGridHelper.js page to be run locally , importing the code from https://mevedia.com/share/InfiniteGridHelper.js?c, import maps, and using a regular script tag. the results tend to cycle between errors like

Uncaught TypeError: THREE.InfiniteGridHelper is not a constructor
http://127.0.0.1:5000/static/main.js:142

"SyntaxError: import declarations may only appear at top level of a module"

Uncaught SyntaxError: The requested module ‘http://127.0.0.1:5000/static/InfiniteGridHelper.js’ doesn’t provide an export named: ‘InfiniteGridHelper’

Uncaught ReferenceError: THREE is not defined
http://127.0.0.1:5000/static/InfiniteGridHelper.js:3

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://mevedia.com/share/InfiniteGridHelper.js?c. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.

There is a forum on this library that seems to have been abandoned but it looks like other people were able to get it to work and it also seems to work on codepen. I’m just not able to figure out a way to get it to run locally.

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// Author: Fyrestar https://mevedia.com (https://github.com/Fyrestar/THREE.InfiniteGridHelper)


THREE.InfiniteGridHelper = function InfiniteGridHelper( size1, size2, color, distance, axes = 'xzy' ) {

    color = color || new THREE.Color( 'white' );
    size1 = size1 || 10;
    size2 = size2 || 100;

    distance = distance || 8000;



    const planeAxes = axes.substr( 0, 2 );

    const geometry = new THREE.PlaneBufferGeometry( 2, 2, 1, 1 );

    const material = new THREE.ShaderMaterial( {

        side: THREE.DoubleSide,

        uniforms: {
            uSize1: {
                value: size1
            },
            uSize2: {
                value: size2
            },
            uColor: {
                value: color
            },
            uDistance: {
                value: distance
            }
        },
        transparent: true,
        vertexShader: `
           
           varying vec3 worldPosition;
           
           uniform float uDistance;
           
           void main() {
           
                vec3 pos = position.${axes} * uDistance;
                pos.${planeAxes} += cameraPosition.${planeAxes};
                
                worldPosition = pos;
                
                gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
           
           }
           `,


        fragmentShader: `
           
           varying vec3 worldPosition;
           
           uniform float uSize1;
           uniform float uSize2;
           uniform vec3 uColor;
           uniform float uDistance;
            
            
            
            float getGrid(float size) {
            
                vec2 r = worldPosition.${planeAxes} / size;
                
                
                vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
                float line = min(grid.x, grid.y);
                
            
                return 1.0 - min(line, 1.0);
            }
            
           void main() {
           
                
                  float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
                
                  float g1 = getGrid(uSize1);
                  float g2 = getGrid(uSize2);
                  
                  
                  gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
                  gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
                
                  if ( gl_FragColor.a <= 0.0 ) discard;
                
           
           }
           
           `,

        extensions: {
            derivatives: true
        }

    } );


    THREE.Mesh.call( this, geometry, material );

    this.frustumCulled = false;

};

THREE.InfiniteGridHelper.prototype = {
    ...THREE.Mesh.prototype,
    ...THREE.Object3D.prototype,
    ...THREE.EventDispatcher.prototype
};

if ( parseInt( THREE.REVISION ) > 126 ) {

    class InfiniteGridHelper extends THREE.Mesh {

        constructor ( size1, size2, color, distance, axes = 'xzy' ) {


            color = color || new THREE.Color( 'white' );
            size1 = size1 || 10;
            size2 = size2 || 100;

            distance = distance || 8000;



            const planeAxes = axes.substr( 0, 2 );

            const geometry = new THREE.PlaneBufferGeometry( 2, 2, 1, 1 );

            const material = new THREE.ShaderMaterial( {

                side: THREE.DoubleSide,

                uniforms: {
                    uSize1: {
                        value: size1
                    },
                    uSize2: {
                        value: size2
                    },
                    uColor: {
                        value: color
                    },
                    uDistance: {
                        value: distance
                    }
                },
                transparent: true,
                vertexShader: `
           
           varying vec3 worldPosition;
           
           uniform float uDistance;
           
           void main() {
           
                vec3 pos = position.${axes} * uDistance;
                pos.${planeAxes} += cameraPosition.${planeAxes};
                
                worldPosition = pos;
                
                gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
           
           }
           `,


                fragmentShader: `
           
           varying vec3 worldPosition;
           
           uniform float uSize1;
           uniform float uSize2;
           uniform vec3 uColor;
           uniform float uDistance;
            
            
            
            float getGrid(float size) {
            
                vec2 r = worldPosition.${planeAxes} / size;
                
                
                vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
                float line = min(grid.x, grid.y);
                
            
                return 1.0 - min(line, 1.0);
            }
            
           void main() {
           
                
                  float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
                
                  float g1 = getGrid(uSize1);
                  float g2 = getGrid(uSize2);
                  
                  
                  gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
                  gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
                
                  if ( gl_FragColor.a <= 0.0 ) discard;
                
           
           }
           
           `,

                extensions: {
                    derivatives: true
                }

            } );

            super( geometry, material );

            this.frustumCulled = false;

        }

    }
    
    Object.assign( InfiniteGridHelper.prototype, THREE.InfiniteGridHelper.prototype );

    THREE.InfiniteGridHelper = InfiniteGridHelper;

}


// creating the scene

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / 
    window.innerHeight, 0.1, 1000);
    camera.position.set(0,0,5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

window.addEventListener('resize',function(){
    var width = window.innerWidth;
    var height = window.innerHeight;
    renderer.setSize(width, height);
    camera.aspect=window.innerWidth/ window.innerHeight;
    camera.updateProjectionMatrix();
})

const controls = new OrbitControls( camera, renderer.domElement );
controls.update()


// Infinite Grid Helper
const gridHelper = new THREE.InfiniteGridHelper(10, 100);
scene.add(gridHelper);
scene.add( gridHelper );

// Create a simple cube
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial(); // MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

function animate() {
    requestAnimationFrame(animate);

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
    controls.update()
}

animate();
<!DOCTYPE html>
<html>
<head>
    <title>Three.js Scene</title>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
        <script type="importmap"> { "imports": 
            { "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js", 
            "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"}} 
        </script>
        <script type="module" src="static/main.js"></script>

</body>
</html>

2

Answers


  1. I tried running your example and I faced the same read-only TypeError.

    Following the way OrbitControls was implemented, I made a few changes in the implementation of the InfiniteGridHelper. So, the proposed implementation is below:

    1. infinite-grid-helper.js
    import * as THREE from 'three';
    
    class InfiniteGridHelper extends THREE.Mesh {
    
      constructor ( size1, size2, color, distance, axes = 'xzy' ) {
    
    
        color = color || new THREE.Color( 'white' );
        size1 = size1 || 10;
        size2 = size2 || 100;
    
        distance = distance || 8000;
    
    
    
        const planeAxes = axes.substr( 0, 2 );
    
        const geometry = new THREE.PlaneGeometry( 2, 2, 1, 1 );
    
        const material = new THREE.ShaderMaterial( {
    
          side: THREE.DoubleSide,
    
          uniforms: {
            uSize1: {
              value: size1
            },
            uSize2: {
              value: size2
            },
            uColor: {
              value: color
            },
            uDistance: {
              value: distance
            }
          },
          transparent: true,
          vertexShader: `
             
             varying vec3 worldPosition;
         
             uniform float uDistance;
             
             void main() {
             
                  vec3 pos = position.${axes} * uDistance;
                  pos.${planeAxes} += cameraPosition.${planeAxes};
                  
                  worldPosition = pos;
                  
                  gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
             
             }
             `,
    
    
          fragmentShader: `
             
             varying vec3 worldPosition;
             
             uniform float uSize1;
             uniform float uSize2;
             uniform vec3 uColor;
             uniform float uDistance;
              
              
              
              float getGrid(float size) {
              
                  vec2 r = worldPosition.${planeAxes} / size;
                  
                  
                  vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
                  float line = min(grid.x, grid.y);
                  
              
                  return 1.0 - min(line, 1.0);
              }
              
             void main() {
             
                  
                    float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
                  
                    float g1 = getGrid(uSize1);
                    float g2 = getGrid(uSize2);
                    
                    
                    gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
                    gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
                  
                    if ( gl_FragColor.a <= 0.0 ) discard;
                  
             
             }
             
             `,
    
          extensions: {
            derivatives: true
          }
    
        } );
    
        super( geometry, material );
    
        this.frustumCulled = false;
    
      }
    
    }
    
    export { InfiniteGridHelper };
    

    An export of the InfiniteGridHelper class was created and taking into account that PlaneBufferGeometry has been deprecated since r145, it was replaced with PlaneGeometry.

    Then, we have to import it to our script:

    1. script.js
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    import { InfiniteGridHelper } from './infinite-grid-helper.js';
    
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / 
        window.innerHeight, 0.1, 1000);
        camera.position.set(0,0,5);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    window.addEventListener('resize',function(){
        var width = window.innerWidth;
        var height = window.innerHeight;
        renderer.setSize(width, height);
        camera.aspect=window.innerWidth/ window.innerHeight;
        camera.updateProjectionMatrix();
    })
    
    const controls = new OrbitControls( camera, renderer.domElement );
    controls.update()
    
    
    // Infinite Grid Helper
    const gridHelper = new InfiniteGridHelper(10, 100);
    scene.add(gridHelper);
    scene.add( gridHelper );
    
    // Create a simple cube
    const geometry = new THREE.BoxGeometry();
    const material = new THREE.MeshNormalMaterial(); // MeshBasicMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    
    function animate() {
        requestAnimationFrame(animate);
    
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
    
        renderer.render(scene, camera);
        controls.update()
    }
    
    animate();
    

    Finally, we have to include it in the HTML file:

    1. index.html
    <!DOCTYPE html>
    <html>
    <head>
        <title>Three.js Scene</title>
        <style>
            body { margin: 0; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>
    <body>
            <script type="importmap"> { "imports": 
                { "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js", 
                "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"}} 
            </script>
            <script type="module" src="infinite-grid-helper.js"></script>
            <script type="module" src="script.js"></script>
    
    </body>
    </html>
    

    Running it from a local server, will produce the following result:

    enter image description here

    Login or Signup to reply.
  2. this module code succesfully loads your script (as import or fetch for that script is not allowed):

    const THREE = await import('three').then(m=>({...m})) // import THREE and return it as object, not module (you cant defineProperty on module)
    window.THREE = THREE                                  // make THREE visible for all scripts
    
    await new Promise((resolve, reject)=>{                // wait till script is loaded
        const script = document.createElement('script')
        document.body.appendChild(script)
        script.onload = ()=>{resolve('loaded')}
        script.src = 'https://mevedia.com/share/InfiniteGridHelper.js?c'
    })
    
    console.log(THREE.InfiniteGridHelper)
    

    console message:

    class InfiniteGridHelper extends THREE.Mesh {
    
            constructor ( size1, size2, color, distance, axes = 'xzy' ) {
    
    
                color = color || new THREE.Color( 'white' );
                size1 = size1 || 10;
                size2 = size2 || …
    

    full code:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script type="importmap">
        {
            "imports": {
                "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
                "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
            }
        }
        </script>
    </head>
    <body>
        <script type="module">
            const THREE = await import('three').then(m=>({...m})) // import THREE and return it as object, not module (you cant defineProperty on module)
            window.THREE = THREE                                  // make THREE visible for all scripts
    
            await new Promise((resolve, reject)=>{                // wait till script is loaded
                const script = document.createElement('script')
                document.body.appendChild(script)
                script.onload = ()=>{resolve('loaded')}
                script.src = 'https://mevedia.com/share/InfiniteGridHelper.js?c'
            })
    
            console.log(THREE.InfiniteGridHelper)
        </script>
    </body>
    </html>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search