简体   繁体   中英

Round Corners Box Geometry - threejs

This question is more about Math, than about threejs but maybe there are usable Alternatives for my issue.

问题示例图片

So what I want to do, is to go through every vertice in a Box Geometry and check weither it has to be moved down/up and move it then by a specific value. (it is only about the y-values of each vertice)

var width = 200,
    height = 100,
    depth = 50;
var roundCornerWidth = var roundCornerHeight = 10;
var helpWidth = width - 2*roundCornerWidth,
    helpHeight = height - 2*roundCornerHeight;

var boxGeometry = new THREE.BoxGeometry(width, height, depth, 100, 50, 10);
boxGeometry.vertices.forEach(v => {
  if(Math.abs(v.x)>helpWidth/2){
    if(Math.abs(v.y)>helpHeight/2){
      let helper = Math.abs(v.x)-helperWidth/2;
      v.y = Math.sign(v.y)*(helperHeight + Math.cos(helper/roundWidth * Math.PI/2)*roundHeight);
    }
  }
});

The code above creates corners like you can see on the example image. Those aren't kind of beautiful! :(
Another "function" than cos() is needed.

I've used a method without trigonometrical functions, as we can manipulate with vectors:

 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); camera.position.set(50, 50, 150); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var controls = new THREE.OrbitControls(camera, renderer.domElement); var radius = 10; var width = 200, height = 100; var geometry = new THREE.BoxGeometry(width, height, 50, 100, 50, 10); var v1 = new THREE.Vector3(); var w1 = (width - (radius * 2)) * 0.5, h1 = (height - (radius * 2)) * 0.5; var vTemp = new THREE.Vector3(), vSign = new THREE.Vector3(), vRad = new THREE.Vector3(); geometry.vertices.forEach(v => { v1.set(w1, h1, vz); vTemp.multiplyVectors(v1, vSign.set(Math.sign(vx), Math.sign(vy), 1)); vRad.subVectors(v, vTemp); if (Math.abs(vx) > v1.x && Math.abs(vy) > v1.y && vRad.length() > radius) { vRad.setLength(radius).add(vTemp); v.copy(vRad); } }); var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: "aqua", wireframe: true })); scene.add(mesh); render(); function render() { requestAnimationFrame(render); renderer.render(scene, camera); }
 body { overflow: hidden; margin: 0; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Disadvantage: you can't control the smoothness of the roundness without increasing the amount of width or height or depth segments.

EDIT : copied surrounding Code Blocks from prisoner849 to make result visbile for everyone.

I wanted to stay with the box Geometry, because I also deform the Geometry on the z-axis, so this is my solution:

 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); camera.position.set(50, 50, 150); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var controls = new THREE.OrbitControls(camera, renderer.domElement); var width = 200, height = 100, depth = 50; var roundCornerWidth = roundCornerHeight = 10; var helpWidth = width - 2*roundCornerWidth, helpHeight = height - 2*roundCornerHeight; var boxGeometry = new THREE.BoxGeometry(width, height, depth, 100, 50, 10); boxGeometry.vertices.forEach(v => { if(Math.abs(vx)>helpWidth/2){ if(Math.abs(vy)>helpHeight/2){ let helperX = Math.abs(vx)-helpWidth/2; let helperY2 = (Math.abs(vy)-helpHeight/2)/roundCornerHeight; let helperY = (1-helperX/roundCornerWidth) * roundCornerHeight * helperY2; vy = Math.sign(vy)*((helpHeight/2 + helperY)+(Math.sin(helperX/roundCornerWidth * Math.PI)*(roundCornerHeight/4))*helperY2); vx = Math.sign(vx)*(Math.abs(vx)+(Math.sin(helperX/roundCornerWidth * Math.PI)*(roundCornerWidth/4))*helperY2); } } }); var mesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({ color: 0xffce00, wireframe: true })); scene.add(mesh); render(); function render() { requestAnimationFrame(render); renderer.render(scene, camera); }
 body { overflow: hidden; margin: 0; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

This worked for me perfectly and seems to be the simplest solution for my issue.

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