Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="overlay">
  (please wait...)
</div>
              
            
!

CSS

              
                body {
  margin: 0;
}

.overlay {
  position: absolute;
  top: 10px;
  left: 50%;
  z-index: 1;
  transform: translateX(-50%);
  color: #ffffff;
  background: #000000;
  border-radius: 2px;
  padding: 10px;
}
              
            
!

JS

              
                import * as THREE from '//cdn.rawgit.com/mrdoob/three.js/master/build/three.module.js';
import { GLTFLoader } from '//cdn.rawgit.com/mrdoob/three.js/master/examples/jsm/loaders/GLTFLoader.js';
import { FBXLoader } from '//cdn.rawgit.com/mrdoob/three.js/master/examples/jsm/loaders/FBXLoader.js';

// NOTE Toggle between rendering cubes and models
const RENDER_OBJECTS = 'gltf'; // box | gltf | fbx
const MAKE_MEMORY_LEAK = true;

const cubeTexture = '//cdn.wtlstudio.com/common-ptr.wtlstudio.com/3d61522d-79ba-4ffe-98a0-864c3a091e87.png';
const gltfModel = '//cdn.wtlstudio.com/sample.wtlstudio.com/48315172-1012-4127-9e52-ed8738ba5e37.glb';

// NOTE Setup - safe to skip to next comment
let meshes = [];
let limit = 0;
let pending = 0;

const gltfLoader = new GLTFLoader();
const fbxLoader = new FBXLoader();
const textureLoader = new THREE.TextureLoader();

const overlayDiv = document.querySelector('.overlay');
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xeff5555);
scene.add(new THREE.AmbientLight(0xffffff, 1.0));
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight);
camera.position.set(-2, 2, 10);

// NOTE Dispose helper
const dispose = (object) => {
  if (!object || typeof object !== 'object') {
    return;
  }

  if (object.children) {
    // Dispose all children first

    object.children.forEach(child => dispose(child));
  }
  
  if (object.parent) {
    // Remove from parent to prevent rerender

    object.parent.remove(object);
  }
  
  if (object.geometry) {
    // Dispose geometry

    object.geometry.dispose();
  }
  
  if (object.material) {
    // Dispose material and all possible textures

    Object.keys(object.material).forEach(key => {
      if (object.material[key] && typeof object.material[key].dispose === 'function') {
        object.material[key].dispose();
      }
    });

    object.material.dispose();
  }
  
  if (typeof object.dispose === 'function') {
    // Dispose object itself

    object.dispose();
  }
};

const animate = () => {
  // Create 20 meshes, then call startDisposing() below

  if (limit < 20 && pending === 0) {
    if (RENDER_OBJECTS === 'gltf') {
      // Fetch new GLTF model

      gltfLoader.load(gltfModel, gltf => {
        // Do this:
        if (!MAKE_MEMORY_LEAK) {
          const children = [];

          gltf.scene.children.forEach(child => children.push(child));

          scene.add(...children);
          meshes.push(...children);
        }

        // Instead of this (memory leak):
        if (MAKE_MEMORY_LEAK) {
          scene.add(gltf.scene);
          meshes.push(gltf.scene);
        }

        pending -= 1;
      });
    } else if (RENDER_OBJECTS === 'fbx') {
      // Fetch new box model (this FBX has no texture)

      fbxLoader.load('//cdn.wtlstudio.com/sample.wtlstudio.com/f1dd4202-bbd2-4d38-baaa-b04c6c7acee3.fbx', (model) => {
        model.scale.setScalar(0.01);
        model.position.copy(new THREE.Vector3().random());
        scene.add(model);

        meshes.push(model);
        pending -= 1;
      });
    } else if (RENDER_OBJECTS === 'box') {
      // Create sample textured cube
      
      const model = new THREE.Mesh(
        new THREE.BoxBufferGeometry(2.0, 2.0, 2.0),
        new THREE.MeshBasicMaterial({
          map: textureLoader.load(cubeTexture, (texture) => {
            model.position.copy(new THREE.Vector3().random());
            scene.add(model);
            meshes.push(model);
          })
        })
      );
      
      pending -= 1;
    }

    limit += 1;
    pending += 1;
  }
  
  if (limit === 20 && pending === 0) {
    limit = 21;
    
    startDisposing();
  }
  
  if (limit > 0) {
    overlayDiv.innerHTML = `
    three: r${THREE.REVISION}<br/>
    mem: ${JSON.stringify(renderer.info.memory)}<br/>
    models: ${meshes.length} / ${Math.min(limit, 20)} (pend.: ${pending})
    `;
  }

  renderer.render(scene, camera);
  requestAnimationFrame(animate);
};

const startDisposing = () => {
  // Delay disposing to ensure 100% of materials and textures are loaded

  setTimeout(() => {
    while (meshes.length > 0) {
      dispose(meshes.pop());
    }
  }, 3000);
};

animate();
document.body.appendChild(renderer.domElement);

              
            
!
999px

Console