Geometry of Rounded Corners Box - three.js

Although this question is primarily related to Math, I believe there may be alternative solutions available within threejs for my particular issue.

My goal is to iterate through each vertex in a Box Geometry and determine whether it needs to be moved up or down by a specific value. In this case, we are only concerned with the y-values of each vertex.

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 current code produces corners similar to those shown in the example image, which are not aesthetically pleasing! :(
We need an alternative method other than using the cos() function.

Answer №1

I have implemented a method that does not involve trigonometric functions, but instead utilizes vector manipulation:

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, v.z);
  vTemp.multiplyVectors(v1, vSign.set(Math.sign(v.x), Math.sign(v.y), 1));
  vRad.subVectors(v, vTemp);
  if (Math.abs(v.x) > v1.x && Math.abs(v.y) > 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>

A limitation is that adjusting the smoothness of the edges requires increasing the number of segments in width, height, or depth.

Answer №2

UPDATE: I decided to include the surrounding Code Blocks from prisoner849 in order to ensure visibility of the final result.

My approach involved sticking with the box Geometry, as I needed to deform the Geometry on the z-axis as well. Here is the solution I came up with:

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(v.x)>helpWidth/2){
    if(Math.abs(v.y)>helpHeight/2){
      let helperX = Math.abs(v.x)-helpWidth/2;
      let helperY2 = (Math.abs(v.y)-helpHeight/2)/roundCornerHeight;
      let helperY = (1-helperX/roundCornerWidth) * roundCornerHeight * helperY2;
      v.y = Math.sign(v.y)*((helpHeight/2 + helperY)+(Math.sin(helperX/roundCornerWidth * Math.PI)*(roundCornerHeight/4))*helperY2);
      v.x = Math.sign(v.x)*(Math.abs(v.x)+(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 approach worked flawlessly for me and appeared to be the most straightforward solution to my problem.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieve data from a server using an Ajax GET request to access information stored within an HTML

Seeking guidance on implementing a jQuery GET request for retrieving specific information from a page structured similar to the following: <tr class='tr'> <td class='example1'> <span> Information I possess ...

Hide the div when hovering occurs

I need a way to hide the 'sample' div when hovering over it and then show it again when the mouse moves away $('.secmenu').hover(function() { $('.sample').css('opacity', '0'); if ($('.secmenu&a ...

What is the best method to trigger a bootstrap modal window from a separate component in Angular 8?

I have successfully implemented a bootstrap modal window that opens on a button click. However, I am now facing difficulty in opening the same modal window from a different component. Below is the code I have tried: <section> <button type=&quo ...

Ajax request terminates once PHP has looped for a specific duration of time (2 minutes)

My challenge involves a button that is responsible for checking over 300 posts for a specific value and other conditions using about 20 if-else statements. Strangely, the ajax call initiated by this button halts after completing around 73 loops within a sp ...

Is there a way to position the weather icon beside the weather condition?

My icon is hanging low on the left corner of the screen. I'm looking for a quick way to move it next to the weather condition (right below Your Location). Access Codepen link <div class="container"> <h1 class=" text-center"> Your Loc ...

Function necessary for successful data binding

The following code is causing an issue for me: <!DOCTYPE html> <html ng-app="m1"> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script> </head> <body> ...

Having trouble getting gulp set up and running with npm?

I am currently in the process of setting up gulp using npm in order to execute my project. Based on my understanding, all I need to do is enter "npm install gulp" in the command line at the location of my project like this : https://i.stack.imgur.com/hPU ...

Getting the highest occurrence of a repeated value within an array using JavaScript (with the help of jQuery)

Dealing with multiple arrays is my current task. I am looking to extract the most duplicated value from each array. In the array [3, 7, 7, 7], the value 7 needs to be found. Each array has a size of 4 elements. Currently, I do not need to consider cases w ...

I encountered a SyntaxError that reads "Unexpected token instanceof" while using the Chrome Javascript console

I find it quite surprising that the code below, when entered into the Chrome JavaScript console: {} instanceof Object leads to the error message displayed below: Uncaught SyntaxError: Unexpected token instanceof Could someone kindly explain why this ...

Cufon failing to load following an ajax call

At first, cufon is used to replace the text on the main page. However, when another page file is loaded, cufon does not apply its replacement to the newly loaded content. Why is that? I tried adding cufon.refresh(); as the last function in the chain. I c ...

Saving the content of a div as a PDF

There are several aspects to consider when it comes to this question, but I'm having trouble finding the information I need. Hopefully someone can provide an answer. Essentially, what I want to achieve is: Imagine a div that is 400 X 400 px in size. ...

Tips for transferring variables between different variables

I'm having trouble transferring the value from a declared variable into another variable. I'm not sure about the correct syntax. Currently, in the code below, the <span id="xevalue1"></span> in my HTML returns nothing, i.e., blank. H ...

Update Calendar Information Without Reloading the Entire Page

Is there a way to automatically refresh a div that includes a FullCalendar Calendar? I'm looking to refresh the div every 30 seconds to check for new data from the database without having to modify the ViewModel or reloading the page. index.html &l ...

Exploring the concept of the imaginary unit "i" in C++: Comparing #define and const methods

I'm interested in determining the most effective method for defining the imaginary constant "i" in C++. I am aware that there have been numerous discussions regarding the use of #define versus const in C++, with the general consensus leaning towards ...

Experience dynamic data transformations with Vue's server-side rendering feature

Incorporating Vue into server-side rendering presents a challenge when the content data within the template needs to be fetched from another CMS server. <template> <h1>{{ content.heading }}</h1> </template> <script> expo ...

Exploring the intricacies of defining Vue component props in TypeScript using Vue.extend()

Here is a simple example to illustrate my question When I directly define my props inside the component, everything works fine <script lang="ts"> import Vue, { PropType } from "vue"; export default Vue.extend({ props: { col ...

Using ngRepeat to Minimize TH-Tags in AngularJS

Here is the current section of TH-Tags in the view: ... <th> <a href="" ng-click="sortReverse = !sortReverse; order('fname',sortReverse)"> Firstname <span ng-show="sortType=='fname' && ...

I am unsure of the timestamp format for the value 1522899000000. Can it be used in both Ionic and AngularJS? And how would one go

While parsing a JSON from an external URL, I came across a timestamp with the value starttime: 1522899000000 (on 4/5/2018 -> 5th April 2018). The value seemed like a Unix timestamp, but when I tried to convert it, it displayed the year 1912. What kind o ...

Is it possible to refresh the browser with a specific URL using Node or Gulp?

Excuse me if this is not the appropriate place to pose my query. Unfortunately, due to the limitations of my workplace/CMS setup, I am unable to access a local version of the website for development purposes. Instead, we are working on CSS and JS locally ...

My page is experiencing delays due to setInterval

Currently, I am delving into the world of Chrome Extension development and am faced with a roadblock in replacing elements on a live chat page. While most of my tasks are running smoothly, the one thing causing issues is the setInterval option that trigger ...