Texturing Irregular Polygons in Three.js: A New Approach

Currently, I am utilizing Three.js to create a polyhedron with various colors and text on each face, all generated from a canvas element. While I am focusing on polyhedra that have native classes in Three.js for now, my goal is to eventually explore more irregular shapes.

There are numerous resources online, such as StackOverflow posts like Three.js cube with different texture on each face, that demonstrate how to achieve this effect with cubes. However, I have not been able to locate any examples showcasing the same technique applied to non-cube shapes. Despite this, the process that works for CubeGeometry seems to also work for TetrahedronGeometry and similar shapes.

Below is a simplified version of the code I am using to generate the polyhedron:

switch (shape) {
    case "ICOSAHEDRON" :

        // Step 1: Create the appropriate geometry.
        geometry = new THREE.IcosahedronGeometry(PolyHeatMap.GEOMETRY_CIRCUMRADIUS);

        // Step 2: Generate individual materials for each face and combine them into one large MeshFaceMaterial.
        material = new THREE.MeshFaceMaterial(createMaterials(20, textArray));

        // Step 3: Assign each face with its corresponding material.
        for (x = 0; face = geometry.faces[x]; x++)
        {
            face.materialIndex = x;
        }
        break;

     // Repeat the above steps for other shapes.
}

function createTexture (title, color) {
    var canvas = document.createElement("canvas");

    // Canvas generation logic goes here.

    var texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;

    return new THREE.MeshLambertMaterial({ map : texture });
}

function createMaterials (numFacets, textArray)
{
    var materialsArray = [],
        material;

    for (var x = 0, xl = numFacets; x < xl; x++)
    {
        material = createTexture(textArray[x], generateColor(textArray[x]));
        material.side = THREE.DoubleSide;
        materials.push(oMaterial); 
    }

    return materials;
}

This technique renders cubes flawlessly, however, when it comes to other polyhedra, the textures do not behave as intended:

It's challenging to pinpoint exactly what is causing the issue. Essentially, while each face displays the correct texture, the texture itself appears stretched and shifted to cover the entire polyhedron. In simpler terms - when viewing the shape head-on, the upper-left face only shows the upper-left portion of its texture, the upper-right face only shows the upper-right portion, and so forth.

The faces on the opposite side of the polyhedron do not show any texture detail at all; just colors.

Prior to experimenting with Three.js, I had no prior experience with 3D rendering. Therefore, I presume there might be a step that CubeGeometry performs automatically but its related classes do not. While I could reference other examples posted online, most focus on rendering cubes or using solid colors.

What adjustments need to be made to properly scale and center the textures on non-cube shapes?

Answer №1

To update the UVs, you can follow this simple example that demonstrates one way to do it.

Check out the code snippet on jsFiddle.

Here's how you can set new coordinates for all faces:


geometry.faceVertexUvs[0] = [];

for(var i = 0; i < geometry.faces.length; i++){                              

    // Set new coordinates for all faces
    geometry.faceVertexUvs[0].push([
        new THREE.Vector2( 0,0 ),
        new THREE.Vector2( 0,1 ),
        new THREE.Vector2( 1,1),
    ]);
}

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

Is it possible to make the info box centered and adjust everything to seamlessly fit on all screen sizes?

Is there a way to create a centered info box that stretches to fit any screen size? ...

Utilizing Arrays for Angular Data Binding with AJAX

I am currently experimenting with loading Ajax data into an array and then binding the array using Angular. Here is my code (I have some experience with KO, so I'm keeping it simple for now): Update: I managed to get it working. I believe the issue w ...

What is the best way to have a sound play when the page is loaded?

Is there a way to automatically play a sound when the page loads? <audio src="song.mp3"> Your browser does not support the audio element. </audio> I've attempted it with the following method: <script type="text/javasc ...

What is the method for passing an element object instead of an id in JSXGraph?

I'm attempting to modify var brd2 = JXG.JSXGraph.initBoard('box', {boundingbox: [-8.75, 2.5, 8.75, -2.5]}); to read as var brd2 = JXG.JSXGraph.initBoard(this.$('#box'), {boundingbox: [-8.75, 2.5, 8.75, -2.5]}); Due to the creat ...

Encasing the Angular 2 component template in a <div> tag

Currently, I have a parent component managing multiple child components. My goal is to enclose each child component's template with a *ngIf directive for conditional rendering. The number of children in the parent component can vary. Here is an examp ...

Adjust the size of a div element with JavaScript

Currently, I am facing a challenge with resizing a div with the id="test". My goal is to adjust the size of the div based on the height of the browser window subtracting 80px so that the element fits perfectly within the visible space without req ...

Receiving no feedback from a public API while coding in React.js

I am currently delving into React.js and have been experimenting with a basic form. The issue I am facing is related to sending form data using ajax and not receiving a response. Upon running the code, the console displays an error message stating readysta ...

What should you do when you need to send a message from a website to an MQTT broker that lacks Websockets support?

Currently venturing into the realm of web development, I find myself tackling a project that involves sending messages from my website to Thingstream, an MQTT broker. My initial attempt using the MQTT Paho JavaScript library was thwarted by the fact that ...

Loading modules conditionally in Nuxt.js

In my Nuxt.js configuration, I have included a module for Google Tag Manager like this: modules: [ [ '@nuxtjs/google-tag-manager', { id: 'GTM-XXXXXXX' } ] ] Everything is functioning properly, but I am curious ab ...

Swapping React components within a list: How to easily change classes

For my latest project, I am building a straightforward ecommerce website. One of the key features on the product page is the ability for users to select different attributes such as sizes and colors. These options are represented by clickable divs that pul ...

Encountering difficulties in creating an app with Apache Cordova

After setting up the proxy settings, I attempted to create a new app named "hello" using Cordova with the following commands: npm config set proxy http://proxy.company.com:8080 npm config set https-proxy http://proxy.company.com:8080 The creation comman ...

Iterate through array starting from the center and moving outwards

I am looking to iterate through an array starting from the middle and moving outwards. var array = [a,b,c,d,e]; The desired order of printing would be: c,d,b,e,a I have managed to divide the array in half and traverse it both forward and backward, but I ...

sending a selection of JSON string values to a jQuery function

I have a JSON string that contains different items, but I am only interested in the 'locked' array and would like to pass it to a jQuery function. The JSON string was generated using json_encode from PHP. {"ignored":[],"status":{"message":"succe ...

Substitute the identifier with an element for a specific webpage

Currently, my navigation consists of two list items: <body id="trips"> <nav> <li><a href="/trips.php" class="trips">Trips</a></li> <li><a href="/trips.php?offer=true" class="offers">Offers< ...

Enhancing elements with fade-in effects upon hovering

Is there a way to incorporate a subtle fade in/fade out effect when hovering over items on this webpage: http://jsfiddle.net/7vKFN/ I'm curious about the best approach to achieve this using jQuery. var $container = $("#color-container"), ...

Issue: [$injector:unpr] The provider ngCsvProvider is not recognized, referenced within the ngCsv module and utilized in the dynamicDemoController

Let me set the stage for you: We have A.js, which defines the main module. We also have B.js, which is lazy-loaded after angular bootstrapping and contains a controller along with some directives. Contents of A.js: var APP = angular.module('app.he ...

Tips for utilizing jQuery buttons to submit forms in PHP

I'm struggling to submit the form using PHP from a button in jQuery. I've tried adding an ID for the button, but I can't seem to submit the values. Since I'm new to jQuery, this task is proving to be a bit challenging. Can anyone provid ...

What exactly is the function of the NextPage feature in Next.js?

Recently, I began incorporating TypeScript into my Next project. Could someone clarify the purpose of the following code snippets for me? import { NextPage } from 'next'; export const Page: NextPage = () => {} After reviewing the documentation ...

The supertest request body cannot be found

Testing my express server POST endpoint using supertest has been a challenge for me. Although everything works perfectly in postman, I encountered an issue when trying to pass body parameters into the test. It seems like the body parameters are not being p ...

Display a loading GIF for every HTTP request made in Angular 4

I am a beginner with Angular and I am looking for a way to display a spinner every time an HTTP request is made. My application consists of multiple components: <component-one></component-one> <component-two></component-two> <c ...