更新5
创建了另一个小提琴以显示预期的外观。添加了不可见的穹顶和魔方相机,并使用了环境贴图;就我而言,由于已经提到的原因,不应使用这些技术。
更新4
重要信息:请注意,目标网格后面有一个反射平面,用于观察纹理是否正确绑定到网格表面,这与我要解决的问题无关。
更新3
创建了一个新的小提琴以显示什么不是预期的行为
- 码
也许我应该重新表述我的问题,但是我缺乏准确地描述我要解决的问题的知识,请提供帮助。也许 .. ?)
更新2
(由于应用了代码段,因此已弃用。)
更新资料
好的..我添加了3种方法:
TransformUv
接受几何图形,以及处理uv变换的变形器方法。回调为每个面接受一个uvs数组,并将对应Face3
的geometry.faces[]
用作其参数。MatcapTransformer
是执行matcap转换的uv变换处理程序回调。和
fixTextureWhenRotateAroundZAxis
就像它的名字一样
到目前为止fixTexture..
,还没有一种方法可以一起工作fixTextureWhenRotateAroundXAxis
。问题仍然没有解决,我希望刚才添加的内容可以帮助您解决问题。
我试图使网格的纹理始终面对主动透视相机,无论相对位置如何。
为了构建场景的真实案例并进行交互会非常复杂,我构建了一个最小的示例来说明我的意图。
- 码
var MatcapTransformer=function(uvs, face) { for(var i=uvs.length; i-->0;) { uvs[i].x=face.vertexNormals[i].x*0.5+0.5; uvs[i].y=face.vertexNormals[i].y*0.5+0.5; } }; var TransformUv=function(geometry, xformer) { // The first argument is also used as an array in the recursive calls // as there's no method overloading in javascript; and so is the callback. var a=arguments[0], callback=arguments[1]; var faceIterator=function(uvFaces, index) { xformer(uvFaces[index], geometry.faces[index]); }; var layerIterator=function(uvLayers, index) { TransformUv(uvLayers[index], faceIterator); }; for(var i=a.length; i-->0;) { callback(a, i); } if(!(i<0)) { TransformUv(geometry.faceVertexUvs, layerIterator); } }; var SetResizeHandler=function(renderer, camera) { var callback=function() { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect=window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); }; // bind the resize event window.addEventListener('resize', callback, false); // return .stop() the function to stop watching window resize return { stop: function() { window.removeEventListener('resize', callback); } }; }; (function() { var fov=45; var aspect=window.innerWidth/window.innerHeight; var loader=new THREE.TextureLoader(); var texture=loader.load('https://i.postimg.cc/mTsN30vx/canyon-s.jpg'); texture.wrapS=THREE.RepeatWrapping; texture.wrapT=THREE.RepeatWrapping; texture.center.set(1/2, 1/2); var geometry=new THREE.SphereGeometry(1, 16, 16); var material=new THREE.MeshBasicMaterial({ 'map': texture }); var mesh=new THREE.Mesh(geometry, material); var geoWireframe=new THREE.WireframeGeometry(geometry); var matWireframe=new THREE.LineBasicMaterial({ 'color': 'red', 'linewidth': 2 }); mesh.add(new THREE.LineSegments(geoWireframe, matWireframe)); var camera=new THREE.PerspectiveCamera(fov, aspect); camera.position.setZ(20); var scene=new THREE.Scene(); scene.add(mesh); { var mirror=new THREE.CubeCamera(.1, 2000, 4096); var geoPlane=new THREE.PlaneGeometry(16, 16); var matPlane=new THREE.MeshBasicMaterial({ 'envMap': mirror.renderTarget.texture }); var plane=new THREE.Mesh(geoPlane, matPlane); plane.add(mirror); plane.position.setZ(-4); plane.lookAt(mesh.position); scene.add(plane); } var renderer=new THREE.WebGLRenderer(); var container=document.getElementById('container1'); container.appendChild(renderer.domElement); SetResizeHandler(renderer, camera); renderer.setSize(window.innerWidth, window.innerHeight); var fixTextureWhenRotateAroundYAxis=function() { mesh.rotation.y+=0.01; texture.offset.set(mesh.rotation.y/(2*Math.PI), 0); }; var fixTextureWhenRotateAroundZAxis=function() { mesh.rotation.z+=0.01; texture.rotation=-mesh.rotation.z TransformUv(geometry, MatcapTransformer); }; // This is wrong var fixTextureWhenRotateAroundAllAxis=function() { mesh.rotation.y+=0.01; mesh.rotation.x+=0.01; mesh.rotation.z+=0.01; // Dun know how to do it correctly .. texture.offset.set(mesh.rotation.y/(2*Math.PI), 0); }; var controls=new THREE.TrackballControls(camera, container); renderer.setAnimationLoop(function() { fixTextureWhenRotateAroundYAxis(); // Uncomment the following line and comment out `fixTextureWhenRotateAroundYAxis` to see the demo // fixTextureWhenRotateAroundZAxis(); // fixTextureWhenRotateAroundAllAxis(); // controls.update(); plane.visible=false; mirror.update(renderer, scene); plane.visible=true; renderer.render(scene, camera); }); })();
body { background-color: #000; margin: 0px; overflow: hidden; }
<script src="https://threejs.org/build/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script> <div id='container1'></div>
请注意,尽管在本演示中网格物体本身会旋转,但我的真正意图是使相机像在网格物体周围旋转一样运动。
我添加了线框以使运动更加清晰。如您所见,我曾经fixTextureWhenRotateAroundYAxis
正确地执行过此操作,但这仅用于y轴。将mesh.rotation.y
在我真正的代码计算像
var ve=camera.position.clone();
ve.sub(mesh.position);
var rotY=Math.atan2(ve.x, ve.z);
var offsetX=rotY/(2*Math.PI);
但是,我缺乏如何fixTextureWhenRotateAroundAllAxis
正确执行的知识。解决此问题有一些限制:
由于客户端计算机可能存在性能问题,因此无法使用CubeCamera / CubeMap
不要简单地将网格
lookAt
划分为摄影机,因为它们最终将具有任何几何形状,不仅是球体。像这样的花招,lookAt
并.quaternion
在框架中还原就可以了。
请不要误会我在问一个XY问题,因为我没有公开专有代码的权利,或者我不必付出努力来构建一个最小的示例:)