简体   繁体   中英

Three.js gltf loader strange behavior when trying to add 3D text

The idea was to load the prebuilt gltf scene made in Blender. Then to add some 3D text using ttf loader and manipulate it. I tried to use a code from examples and each loader works perfectly when I use them separately. But when I combine them into a single script really strange stuff starts happening. When I add a gltf scene first and after that, I add 3D text, the text magically disappears. Console says nothing. I tried to change the order of loading. When I load text after gltf, the content of gltf disappears and the only text stays visible. Screenshot:

奇怪的 gltf 加载器行为

Console says

three.module.js:16177 Uncaught TypeError: Cannot read property 'type' of undefined
    at WebGLIndexedBufferRenderer.setIndex (three.module.js:16177)
    at WebGLRenderer.renderBufferDirect (three.module.js:23910)
    at renderObject (three.module.js:24601)
    at renderObjects (three.module.js:24571)
    at WebGLRenderer.render (three.module.js:24350)
    at render (main.js:73)
    at onAnimationFrame (<anonymous>:116:3)
    at <anonymous>:85:5

By excluding one-by-one item I figured out that this happens only when there's more than one 3D geometry object in gltf. When there's only one geometry object in gltf everything works fine. I suggest there's something with the internal order of the objects, but have no idea how to fix this. Can someone explain to me what did I do wrong.

Here the code:

import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
import * as THREE from './libs/three.module.js';
import { TTFLoader } from './jsm/loaders/TTFLoader.js';

var container;
var camera, cameraTarget, scene, renderer;
var mixer;
var clock = new THREE.Clock();

var group, textMesh1, textGeo, material;
var firstLetter = false;
var text = 'ttf',
    height = 0,
    size = 1,
    hover = 0,
    curveSegments = 4,
    bevelThickness = .1,
    bevelSize = 0;
var font = null;

container = document.createElement( 'div' );
document.body.appendChild( container );

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1500 );
camera.position.set( 0, -10, 10 );
camera.zoom=1.5;
cameraTarget = new THREE.Vector3( 0, 0, 0 );
camera.lookAt( cameraTarget );
scene.add( camera );
camera.updateProjectionMatrix();



var loader = new GLTFLoader();
//loader.load( './text.gltf' , function ( gltf ) { //this one works fine
loader.load( './text+cube.gltf' , function ( gltf ) { //this one acts very strange
    scene.add( gltf.scene );
});


var material = new THREE.MeshPhongMaterial({'color': '#cece00'});
var loader2 = new TTFLoader();
loader2.load( 'fonts/ttf/kenpixel.ttf', function ( json ) {
    font = new THREE.Font( json );
    createText();
} );



var pointLight = new THREE.PointLight( 0xffffff, 2 );
pointLight.position.set( 0, -50, 90 );
scene.add( pointLight );

renderer = new THREE.WebGLRenderer( { antialias: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false ); 
render();

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}

function render() {
    requestAnimationFrame(render);
    var delta = clock.getDelta();
    if (mixer != null) {mixer.update(delta);};
    renderer.render(scene, camera);
}



function createText() {
    textGeo = new THREE.TextBufferGeometry( text, {
        font: font,
        size: size,
        height: height,
        curveSegments: curveSegments,
        bevelThickness: bevelThickness,
        bevelSize: bevelSize,
        bevelEnabled: true
    } );

    textGeo.computeBoundingBox();
    textGeo.computeVertexNormals();
    var centerOffset = - 0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
    textMesh1 = new THREE.Mesh( textGeo, material );
    textMesh1.position.x = centerOffset;
    textMesh1.position.y = hover;
    textMesh1.position.z = 0;
    textMesh1.rotation.x = 0;
    textMesh1.rotation.y = 0;
    scene.add( textMesh1 );
}

html:

<!DOCTYPE html>
<html>
<head>
    <title>!!!TEST!!!</title>
    <style type="text/css">
        html, body {margin: 0; padding: 0; overflow: hidden}
    </style>


</head>
<body>
    <script src="/libs/opentype.min.js"></script>
    <script src="./main.js" type="module"></script>
</body>
</html>

project files

Solved! I imported from libs/three.module.js while GLTFLoader and TTFLoader both depend on the copy in build/three.module.js. Replaced

import * as THREE from './libs/three.module.js';

with

import * as THREE from './build/three.module.js';

(thanks @donmccurdy from the official Three.js forum)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM