首页 > 解决方案 > 三个js中网格的中间挤压

问题描述

我目前正在创建一个三个 js 应用程序,我只想问这是否可能。所以我的目标是在搅拌机中创建一个模型,就像下图中的网格 #1,通过 KhronosGroup 的 blender gltf 导出器将其导出,将其导入三个 JS 并在中间挤出网格以实现下图中的网格 #2。

这样做的原因是我需要显示一个可以具有动态长度的模型,并让用户通过应用程序的 UI 控制模型的长度。

这可能吗?如果没有,有没有办法让我实现我需要完成的行为?

在此处输入图像描述

标签: javascriptthree.js3dblender

解决方案


将模型缩小到一个单位 bbox,并使用自定义顶点着色器来根据模型空间位置操作顶点。

const vs = `
uniform float uWidthModifier;
void main() 
{
  vec3 p = position;
  if (p.x > 0.33) {
    p.x += 0.5 * uWidthModifier;
  } else if (p.x < -0.33) {
    p.x -= 0.5 * uWidthModifier;
  }
	vec4 modelViewPosition = modelViewMatrix * vec4(p, 1.0);
	gl_Position = projectionMatrix * modelViewPosition;
}
`;

const fs = `
void main() {
	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer();
let geometry = new THREE.BoxGeometry(2, 2, 2, 4, 1, 1);
let material = new THREE.ShaderMaterial({
  uniforms: {
    uWidthModifier: { value: 0 }
  },
  fragmentShader: fs,
  vertexShader: vs,
  wireframe: true
});
let cube = new THREE.Mesh(geometry, material);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.add(cube);
camera.position.z = 5;

document.getElementById('inc').addEventListener('click', function() {
  material.uniforms.uWidthModifier.value += 0.5;
});
document.getElementById('dec').addEventListener('click', function() {
  material.uniforms.uWidthModifier.value -= 0.5;
});

function animate() {
	requestAnimationFrame(animate);
  cube.rotation.y += 0.01;
	renderer.render(scene, camera);
}
animate();
#config {
  color: white;
  position: absolute;
  z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.js"></script>
<div id="config">
  uWidthModifier:
  <button id="inc">+</button>
  <button id="dec">-</button>
</div>


推荐阅读