Bee
Bee

Reputation: 33

Middle extrusion for mesh in Three js

I'm currently creating a three js app and I just want to ask if this is possible. So my goal is create a model in blender that's like mesh #1 on the image below, export it thru blender gltf exporter by KhronosGroup, import it in Three JS and extrude the mesh in the middle to achieve mesh #2 in the image below.

The reason for doing this is I need to display a model that could have a dynamic length and let user control the length of the model thru the app's UI.

Is this possible? If not, is there a way for me to achieve the behavior that I need to accomplish?

enter image description here

Upvotes: 0

Views: 336

Answers (1)

Petr Broz
Petr Broz

Reputation: 9934

Scale the model down to a unit bbox, and use a custom vertex shader that manipulates the vertices based on their model space location.

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>

Upvotes: 1

Related Questions