Tips for repairing texture distortion on rounded corner surfaces in the three.js library

I managed to create a unique rounded corner plane by combining circle and plane geometries in my project.

While the flat color in the rendered version looks great, I noticed that the textured part seems to get distorted and chopped up.

If you want to take a look at the code and the project, you can visit this link.

My assumption is that I might need to provide some kind of hint or define the rendering process for the texture, but I'm not entirely sure how to go about it.

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 90, 1, 0.1, 1000 );

WIDTH = HEIGHT = 500

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor( 0xffffff );
renderer.setSize(WIDTH, HEIGHT);

light = new THREE.PointLight(0xffffff);
light.position.set(0,0,100);
scene.add(light);

# 628 × 697


camera.position.z = 5;

document.body.appendChild(renderer.domElement);


meshA = new THREE.Mesh()


generateRoundedCornerPlane = (offset=2, radius=2, smooth=16) ->

    geometry = new THREE.Geometry()

    offset = (offset - radius) / 2
    radius = radius / 4
    smooth = 16

    cornerA = new THREE.CircleGeometry(radius, smooth, (Math.PI * 2 / 4) * 1, Math.PI * 2 / 4);
    matrixA = new THREE.Matrix4();
    matrixA.makeTranslation(0-offset, 0+offset, 0)
    geometry.merge(cornerA, matrixA)

    cornerB = new THREE.CircleGeometry(radius, smooth, (Math.PI * 2 / 4) * 0, Math.PI * 2 / 4);
    matrixB = new THREE.Matrix4();
    matrixB.makeTranslation(0+offset, 0+offset, 0)
    geometry.merge(cornerB, matrixB)

    cornerC = new THREE.CircleGeometry(radius, smooth, (Math.PI * 2 / 4) * 3, Math.PI * 2 / 4);
    matrixC = new THREE.Matrix4();
    matrixC.makeTranslation(0+offset, 0-offset, 0)
    geometry.merge(cornerC, matrixC)

    cornerD = new THREE.CircleGeometry(radius, smooth, (Math.PI * 2 / 4) * 2, Math.PI * 2 / 4);
    matrixD = new THREE.Matrix4();
    matrixD.makeTranslation(0-offset, 0-offset, 0)
    geometry.merge(cornerD, matrixD)

    planeA = new THREE.PlaneGeometry((offset+radius) * 2, offset * 2)
    geometry.merge(planeA)

    planeB = new THREE.PlaneGeometry(offset * 2, (offset+radius) * 2)
    geometry.merge(planeB)

    return geometry

meshA.geometry = generateRoundedCornerPlane(2, 0.5)

meshA.material = new THREE.MeshBasicMaterial
    side:THREE.DoubleSide
    color: new THREE.Color("rgb(255,0,0)")
    #wireframe: true

meshB = new THREE.Mesh()
meshB.geometry = generateRoundedCornerPlane(2, 0.5)

meshB.material = new THREE.MeshBasicMaterial
    side:THREE.DoubleSide
    color: new THREE.Color("rgb(255,0,0)")
    #wireframe: true

texture = new THREE.ImageUtils.loadTexture("/img/initializing.png");
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
meshB.material.map = texture
meshB.material.color = new THREE.Color(0xffffff)

meshB.position.x = -1
meshB.position.y = -1

scene.add(meshA)
scene.add(meshB)

update = ->
    # meshA.scale.x += 0.001
    # meshA.scale.y += 0.001
    meshA.rotation.z += 0.002
    meshA.rotation.y += 0.002
    meshB.rotation.z += 0.002
    meshB.rotation.y += 0.002

render = ->
    renderer.render(scene, camera)

tick = ->
    window.requestAnimationFrame(tick)
    update()
    render()

tick()

Answer №1

To properly map an image onto the faces of a mesh, you must ensure the UV coordinates are correct. Each face in the mesh needs to have accurate UV Coordinates for GL to understand how to apply the texture. The UV Coordinate (0,0) should be at the top left corner of the face, while (1,1) should be at the bottom right corner.

One approach is to iterate through each face and assign normalized UV coordinates based on their spatial position. This method can work well for simple shapes like the one in your example. By calculating the bounding box of the shape, you can normalize the vertex coordinates and create 3 UV Coordinates for each face (as each face is a triangle).

Here's a possible solution: http://jsfiddle.net/MacroMeez/e84y9bbq/1/

remapUVs = (geo) ->
geo.computeBoundingBox()
min = geo.boundingBox.min
max = geo.boundingBox.max
offset = new THREE.Vector2(0 - min.x, 0 - min.y)
size = new THREE.Vector2(max.x - min.x, max.y - min.y)
# Clear the old, incorrect UVs
geo.faceVertexUvs[0] = []
for face, i in geo.faces
    v1 = geo.vertices[face.a]
    v2 = geo.vertices[face.b]
    v3 = geo.vertices[face.c]
    # Calculate and assign new UV coordinates
    geo.faceVertexUvs[0].push [
        new THREE.Vector2((v1.x + offset.x)/size.x, (v1.y + offset.y)/size.y),
        new THREE.Vector2((v2.x + offset.x)/size.x, (v2.y + offset.y)/size.y),
        new THREE.Vector2((v3.x + offset.x)/size.x, (v3.y + offset.y)/size.y)
    ]
geo.uvsNeedUpdate = true

Referenced from THREE.js generate UV coordinate

If you're comfortable with software like Blender, you can also create and map the mesh there before importing it, saving you from dealing with this UV coordinate adjustment.

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

An issue occurred while trying to use the next() method with passport.authenticate('local') function

My current middleware setup involves the use of passport.js for user authentication before moving on to the next middleware: exports.authenticate = (req, res, next) => { passport.authenticate('local', (err, user, info) => { console.l ...

The Ajax search box displays results from the most recent query

Hey there, I need some assistance with a request: var searchResults = new Array(); var ajaxRequest = function (value, type) { if (typeof(type) === "undefined") type = "default"; var ajaxData = { "title" : value, "limit" : ...

Difficulty persisting when removing accents/diacritics from a string in Angular with IE 11

When attempting to utilize the String.normalize("NFD").replace(/[\u0300-\u036f]/g, "") method, I encountered an issue in IE11. ERROR TypeError: The object does not support the property or method "normalize" ...

How to use the Enter key to submit a form in react.js with the help of "@material-ui/core/Button"

Here is the form I have created using the render method for user sign-in. <form onSubmit={this.handleSubmit}> <Avatar className={classes.avatar}> <LockOutlinedIcon /> </Avatar> <Typography component="h1" varia ...

Tricks for preventing axios from caching in GET requests

I am utilizing axios in my React-Native application Firstly, I set up the headers function setupHeaders() { // After testing all three lines below, none of them worked axios.defaults.headers.common["Pragma"] = "no-cache"; axios.defaults.heade ...

Shorten Text - React Native

I currently have a React Native application with a FlatList component. The logic I initially implemented was to display an Expand/Collapse arrow whenever the content at the 100th position in the list is not empty. However, I now realize that this approach ...

Refresh the div based on the script's output

Currently, I am struggling to make a password change form work properly as I have limited knowledge of jQuery. The form successfully changes the password, but there is no visual feedback for the user. When I submit the form, it routes to changePassword.php ...

What is the best way to retrieve an object from a POST request using Angular AJAX calls in a NODEJS environment?

When the button is clicked, a method will be called. The code for this is as follows: .controller('templeDetailsList', function ($scope, $http, $ionicModal) { $scope.starclick = function(){ var newFav = [{ ...

Apply the "ng-class" directive only if there is an <a> element located after the specified element

My issue involves a list of items categorized by labels, with a search filter applied. The problem arises when the labels appear in the search results even though the lists themselves are empty. I need to hide the relevant label if there are no items prese ...

Unconventional JavaScript Variable Declaration

While going through some source code, I stumbled upon this peculiar variable declaration that has me a bit confused. let eventsEnabled : ?boolean = null; Can someone explain what exactly this means? You can find the source code here. ...

Collaborative JavaScript repository within the Websphere Liberty platform

Is it possible to utilize a JavaScript library (such as Dojo, JQuery, or other custom developed libraries) as shared libraries within a Websphere Liberty server? For instance, I am interested in storing the .js files in either C:\wlp\usr\sh ...

Unable to locate npm module called stream

For some reason, our tests have stopped running since yesterday. The error message reads: module stream not found Upon investigation, we discovered that 'stream' is available as a core node module: https://nodejs.org/api/stream.html#apicontent ...

Finding the automatically generated ID of a new document in a subcollection in Firebase Firestore Web V9, using Javascript/React

When a user clicks, I generate a new document in a subcollection associated with that user's profile. Below is the function responsible for this: // Function to create a new checkout session document in the subcollection under the user's profile ...

"Exploring the power of Vue3's composition API in managing the

Trying to implement an accordion component in Vue 3, but encountering a strange comparison issue. I'm attempting to execute a function within the accordionitem - specifically the toggle operation. However, despite numerous attempts, I am unable to mo ...

Request to api.upcitemdb.com endpoint encountering CORS issue

This code may seem simple, but for some reason, it's not working as expected. What I'm trying to achieve is to call the GET API at: I want to make this API call using either JavaScript or jQuery. I've attempted various approaches, but none ...

Exploring the depths of JavaScript JSON elements

After processing my PHP code, it generates a JSON output that contains multiple entries in the same structure. Here is an example with two entries: { "0": { "campaign_id": "31", "title": "new title", "description": "new descrip ...

Javascript: Uncaught TypeError - Unable to assign value to non-existent property

I am having an issue with assigning a value to a textbox, and I keep getting this error. Here is my code: This is the textbox in question: <input id="Text1" type="text" runat="server"/> Here is the dropdown list used in the function: <select i ...

A guide on how to efficiently retrieve all images stored in a specific directory

I attempted to showcase all the images from a single directory using jQuery, but unfortunately it is not functioning as expected. My folder setup includes an 'images' folder and a 'js' folder. I followed this question on Stack Overflow ...

Demonstrate a array of values at varying angles within a circle using the functionalities of HTML5 canvas

Looking to utilize HTML5 Canvas and Javascript for a project where I need to showcase various values (depicted by dots possibly) at different angles within a circle. For example, data could include: val 34% @ 0°, val 54% @ 12°, val 23% @ 70°, a ...

dynamic text overlay on a bootstrap carousel

Having limited knowledge in html and css, I am using a bootstrap carousel slider with text. I am trying to change the color of the box randomly. https://i.sstatic.net/TozUP.jpg Here is the code that I am currently using: <ol class="carousel-indicato ...