Calculate the unique UV coordinates for a custom Buffer Geometry in THREE.JS

I am currently working on creating a curved wall using a vertices array in three JS. The array contains some base vertices in 2D which represent the bottom vertices of the wall. These vertices include the center, lower, and upper points, making it a two-faced wall. By adding a wall height to these vertices, I convert the 2D array to a 3D wall.
Below you can find the code and a working fiddle for reference.

/**
 * Created by Singh on 7/30/2018.
 */

var renderer, scene, camera;

init();
animate();

function init() {
    // Walls Geometry Function
    wallsGeometry = function(totalPoints){
        // Implementation Details
    };

    // Camera Setup
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.z = 400;

    // Scene Setup
    scene = new THREE.Scene();

    // Renderer Setup
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    // Adding Event Listener for Mouse Move
    renderer.domElement.addEventListener("mousemove", onMouseMove);

    // Initializing Points
    initPoints();

    // Creating Walls Geometry
    var mesh = new wallsGeometry(totalPoints);

    // Creating Arrow
    createArrow();

    // Adding Walls to the Scene
    scene.add(mesh[0]);
    scene.add(mesh[1]);

    // Orbit Controls
    var Orbitcontrols = new THREE.OrbitControls(camera,renderer.domElement);
    Orbitcontrols.update();
}

// Render Function
function render() {
    renderer.render(scene, camera);
}

// Animate Function
function animate() {
    requestAnimationFrame(animate);
    render();
}

https://jsfiddle.net/simar_aneja/fsmw8znq/6/

The fiddle demonstrates the successful building of the wall. I am now looking to add UVs to the bufferGeometry in order to attach different textures to different sides of the wall. I have attempted to convert it to geometry and calculate faceVertexUVs, but this approach seems ineffective. I am seeking suggestions on how to proceed further, specifically in attaching different textures to the front and top sides of the wall. Additionally, I aim for a solution where the UVs are calculated dynamically based on the length of the vertices, accommodating any number of vertices that may be added in the future.

Thank you for your help.

Answer №1

Here's a UV box-unwrapping code snippet that I have enhanced for you. Hopefully, you will find it informative...

I have also included a snippet below that allows you to run your fiddle...

function boxUnwrapUVs(geometry) {
  if (!geometry.boundingBox) geometry.computeBoundingBox();
  var sz = geometry.boundingBox.getSize(new THREE.Vector3());
  var center = geometry.boundingBox.getCenter(new THREE.Vector3())
  var min = geometry.boundingBox.min;
  if (geometry.faceVertexUvs[0].length == 0) {
    for (var i = 0; i < geometry.faces.length; i++) {
      geometry.faceVertexUvs[0].push([new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2()]);
    }
  }
  for (var i = 0; i < geometry.faces.length; i++) {
    var face = geometry.faces[i];
    var faceUVs = geometry.faceVertexUvs[0][i]
    var va = geometry.vertices[geometry.faces[i].a]
    var vb = geometry.vertices[geometry.faces[i].b]
    var vc = geometry.vertices[geometry.faces[i].c]
    var vab = new THREE.Vector3().copy(vb).sub(va)
    var vac = new THREE.Vector3().copy(vc).sub(va)
    var vcross = new THREE.Vector3().copy(vab).cross(vac);
    vcross.set(Math.abs(vcross.x), Math.abs(vcross.y), Math.abs(vcross.z))
    var majorAxis = vcross.x > vcross.y ? (vcross.x > vcross.z ? 'x' : vcross.y > vcross.z ? 'y' : vcross.y > vcross.z) : vcross.y > vcross.z ? 'y' : 'z'
    var uAxis = majorAxis == 'x' ? 'y' : majorAxis == 'y' ? 'x' : 'x';
    var vAxis = majorAxis == 'x' ? 'z' : majorAxis == 'y' ? 'z' : 'y';
    faceUVs[0].set((va[uAxis] - min[uAxis]) / sz[uAxis], (va[vAxis] - min[vAxis]) / sz[vAxis])
    faceUVs[1].set((vb[uAxis] - min[uAxis]) / sz[uAxis], (vb[vAxis] - min[vAxis]) / sz[vAxis])
    faceUVs[2].set((vc[uAxis] - min[uAxis]) / sz[uAxis], (vc[vAxis] - min[vAxis]) / sz[vAxis])
  }
  geometry.elementsNeedUpdate = geometry.verticesNeedUpdate = true;
}
geometry = new THREE.Geometry().fromBufferGeometry(geometry)
boxUnwrapUVs(geometry)
var mesh = new THREE.Mesh(geometry, material);

/**
 * Created by Singh on 7/30/2018.
 */

var renderer, scene, camera;

// Function to create geometry for walls
wallsGeometry = function(totalPoints) {

    var rrnd = (min, max) => (Math.random() * (max - min)) + min
    var irnd = (rng) => (Math.random() * rng) | 0

    // Function to create random canvas
    function makeRndCanvas() {
        var canvas = document.createElement('canvas');
        canvas.width = canvas.height = 128;
        var ctx = canvas.getContext('2d');
        var srnd = (rng) => (Math.random() - 0.5) * 2 * rng
        var irnd = (rng) => ((Math.random() * rng) | 0)
        for (var x = 0; x < canvas.width; x++) {
            for (var y = 0; y < canvas.width; y++) {
                ctx.fillStyle = `rgba(${irnd(256)},${irnd(256)},${irnd(256)},1.0)`
                ctx.fillRect(x, y, 1, 1);
            }
        }
        ctx.fillStyle = '#ffff00'
        ctx.fillText("WAHOO", 3, 64)
        return canvas;
    }

    // Function to create random texture
    function makeRndTexture() {
        var tex = new THREE.Texture(makeRndCanvas())
        tex.minFilter = THREE.NearestFilter;
        tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
        tex.needsUpdate = true;
        return tex;
    }

    var material = new THREE.MeshLambertMaterial({
        side: THREE.DoubleSide,
        wireframe: false,
        map: makeRndTexture()
    });
    var material2 = new THREE.MeshLambertMaterial({
        side: THREE.DoubleSide,
        wireframe: true
    });

    var geometry = new THREE.BufferGeometry();
    var geometry2 = new THREE.BufferGeometry();

    var wallHeight = 200;

    /* Code continuation omitted for brevity */

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

What is the process for incorporating Express.js variables into SQL queries?

Recently delving into the world of node.js, I've embarked on a journey to create a login and registration system using express.js, vanilla JS, CSS, HTML, and MySql. Within the following code lies the logic for routing and handling HTTP Post requests ...

Connecting users from a mobile website to a particular item within the Amazon application

Recently, I've been working on linking from my mobile site to a particular item within the Amazon app. My JavaScript code includes a try/catch block that redirects users to the webpage if they don't have the app installed. However, I've foun ...

Tips on transferring dynamically generated results to a user-friendly print window

After users complete a quiz, they receive their results. The client now wants to implement a "Print Results" feature that opens in a new window with customized CSS. I'm trying to figure out how to transfer the results to the new window using JavaScri ...

Execute a function using a click event within a statement

Is it possible to trigger a function with parameters based on the result of a statement? For example, can we achieve something like this: (click)="datavalue.elementDataCollection.length > 1 ? AddNewDialog (datavalue,datavalue.COCLabel,mainindex,i) : r ...

Is Proxy.apply() not functioning correctly on Node.js? I'm unsure if this is a bug or if I am implementing it incorrectly

Utilizing a Proxy object has been quite helpful for me. The getter and setter functions are working perfectly as expected. However, I have encountered an issue where the apply method is never invoked. var p = new Proxy({}, { /* getter */ get(t ...

"Experience the power of utilizing TypeScript with the seamless compatibility provided by the

I'm attempting to utilize jsymal.safeDump(somedata). So far, I've executed npm install --save-dev @types/js-yaml I've also configured my tsconfig file as: { "compilerOptions": { "types": [ "cypress" ...

The functionality of .map() in Javascript is non-existent

I am completely new to this community (and JavaScript is also new for me), so I apologize in advance for asking some very basic questions. I have an HTML page with various images, all of which share a common class. After using getElementsByClassName, I obt ...

Jquery script that utilizes the Steam WebAPI to return data

I'm encountering an issue with a script I found on github. I added value.appid myself, thinking it was logical, but I believe that data.response.games contains values for all my games. How can I either print or view what is defined? I would like to ...

Displaying JSON data dynamically by iterating through it in a loop

While working with JSON data in a loop, I noticed that the code quality does not meet my expectations. I have a feeling that I might be missing something in my approach. $(function(){ $.getJSON('data.json', function(data){ let content ...

Steps for breaking down a given string into divisions that correspond to an A4 sheet

Within my content, there are various styles applied. For example: This is a <b>bolded</b> word. I am seeking a solution to divide this long string into smaller sections that would fit on an A4 page accurately. The goal is to maintain the integ ...

ajax modal form editing

Encountered an issue with editing a form using modal ajax, where the edit form pops up but the data remains empty. The code snippet for my controller: public function edit() { $id=$this->uri->segment(3); $data=array( 'project' => $th ...

Correctly referencing a variable in a delayed AJAX request is crucial for ensuring the proper execution

I am facing an issue with a function called fetchAlbum. This function sets up a placeholder, sends an AJAX request, and updates the placeholder upon success. Here is the code snippet: function fetchAlbum() { albumCounter++; var albumElement = $(&a ...

An unexpected error occurred in the Angular unit and integration tests, throwing off the script

I seem to be facing a recurring issue while running unit/integration tests for my Angular project using Karma. The tests have a 50:50 success/failure rate, working fine on my machine but failing consistently on our build server, making the process quite un ...

Is there a specific index range in javascript or nodejs for accessing array items?

I recently came across this Ruby code snippet: module Plutus TAX_RATES = { (0..18_200) => { base_tax_amount: 0, tax_rate: 0 }, (18_201..37_000) => { base_tax_amount: 0, tax_rate: 0.19 }, (37_001..80_0 ...

Integrate PEM certificate into an Http Request with AngularJS/NodeJS

Currently, I am working on an application that requires retrieving data from a REST endpoint within an encrypted network. Accessing this data is only possible by physically being present (which is currently not an option) or using a PEM certificate provide ...

Using Node.js, Handlebars, and Express for template inheritance

As I embark on my Node.js learning journey, I am starting with creating simple applications to grasp the fundamentals. Recently, I wanted to implement a Django-like template structure in my projects but found myself stuck on how to achieve it. I have come ...

When a jQuery click event is triggered, the event.target will return the child element that was clicked within the

When I have a jQuery click event assigned to a hyperlink that contains an image, each with separate ids, I expect clicking the hyperlink to trigger the code event.target.id, returning the hyperlink's id. However, it actually returns the image's i ...

Learn how to implement Basic Authentication in your Express application using the express-basic-auth package. You can easily trigger login and logout

When it comes to logging out a user who has logged in using basic Auth, I am exploring different options by consulting various sources like: link1 link2 In my application, I have implemented express-basic-auth to secure certain routes. Here is an example ...

Deliver the event target within the data-bind click HTML

I am having trouble sending the event target when passing parameters in data-bind. <button class="tablinks" data-bind="click:$root.notify.bind(this, 1, 'foo');" id="defaultOpen">PRINCIPAL</button> self.notify = function (str, id, e) ...

Choose the initial division within the table and switch the class

Here is a straightforward request - I need to employ jquery to target the first div with the class of "boxgrid captionfull" within the tr element with the classes "row-1 row-first," and switch the class to 'active_labBeitrag'. <table class="v ...