以上效果只有上下两面展好了uv,时间问题其他面没有展uv
threejs 版本 0.143.0
这个版本的几何和老版本的有区别,取消了Geomety ,取而代之的是BufferGeometry ,也没有Face3, 现在是用index 索引的方式链接面。有个困扰就是Face3里面的materialIndex在新版里面怎么实现,这里用的groups 这个属性结构是
[{start: xx, count: xx, materialIndex:xx}]
大致意思就是 从start下标开始,向后count个结束,使用materialIndex材质。注意这里的下标是index索引的下标,结合结合以下代码更好理解
代码
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - geometry - cube</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <link type="text/css" rel="stylesheet" href="main.css"> </head> <body> <!-- Import maps polyfill --> <!-- Remove this when import maps will be widely supported --> <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "../build/three.module.js", "three/addons/": "./jsm/" } } </script> <script type="module"> import * as THREE from 'three'; let camera, scene, renderer; let mesh; init(); animate(); function init() { camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 400; scene = new THREE.Scene(); const texture = new THREE.TextureLoader().load( 'textures/crate.gif' ); let geometry = new THREE.BufferGeometry(); let geoData = []; let index = []; let num = 100; // 顶点 法线 uv geoData.push({position : [num, num, num], normal : [0, 1, 0], uv : [0, 0]}); geoData.push({position : [num, num, -num], normal : [0, 1, 0], uv : [1, 0]}); geoData.push({position : [-num, num, -num], normal : [0, 1, 0], uv : [1, 1]}); geoData.push({position : [-num, num, num], normal : [0, 1, 0], uv : [0, 1]}); geoData.push({position : [num, -num, num], normal : [0, 1, 0], uv : [0, 0]}); geoData.push({position : [num, -num, -num], normal : [0, 1, 0], uv : [1, 0]}); geoData.push({position : [-num, -num, -num], normal : [0, 1, 0], uv : [1, 1]}); geoData.push({position : [-num, -num, num], normal : [0, 1, 0], uv : [0, 1]}); paseData(geoData, geometry); // 索引 index = [0,4,5, 0,5,1, 1,5,6, 1,6,2, 2,6,7, 2,7,3, 3,7,4, 3,4,0, 0,2,3, 0,1,2, 4,7,6, 4,6,5]; const indexs = new Uint16Array(index); geometry.index = new THREE.BufferAttribute(indexs, 1); // 材质 let mat = []; mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0xff0000, } )); // 材质0 mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0x00ff00, } )); // 材质1 mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0x0000ff, } )); // 材质2 mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0xffff00, } )); // 材质3 mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0x00ffff, } )); // 材质4 mat.push(new THREE.MeshBasicMaterial( {map:texture, color: 0xffff00, } )); // 材质5 // 索引(面)与材质关联 let groups = []; groups.push({start: 0, count: 6, materialIndex:0}); // 0-6 index[0,4,5, 0,5,1] 用材质1 groups.push({start: 6, count: 6, materialIndex:1}); // 6-12 index[1,5,6, 1,6,2] 用材质2 groups.push({start: 12, count: 6, materialIndex:2}); groups.push({start: 18, count: 6, materialIndex:3}); groups.push({start: 24, count: 6, materialIndex:4}); groups.push({start: 30, count: 6, materialIndex:5}); geometry.groups = groups; // geometry.computeVertexNormals(); mesh = new THREE.Mesh( geometry, mat ); scene.add( mesh ); renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); window.addEventListener( 'resize', onWindowResize ); } function paseData(geoData, geometry){ let position = []; let normal = []; let uv = []; geoData.forEach(e => { position = position.concat(e.position); normal = normal.concat(e.normal); uv = uv.concat(e.uv); }); geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position), 3)); geometry.setAttribute("normal", new THREE.BufferAttribute(new Float32Array(normal), 3)); geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uv), 2)); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.x += 0.05; mesh.rotation.y += 0.01; renderer.render( scene, camera ); } </script> </body> </html>