Displaying multiple images on the face of a cylinder using three.js

I am struggling to showcase multiple images on the outer surface (not the top or bottom) of a rotating cylinder using three.js. I have managed to display one image successfully, but my objective is to exhibit several side by side. Despite adding three textures to my materials array, only the first one appears. Any assistance would be greatly appreciated.

<html>
<head>
    <title>My Initial three.js Creation</title>
    <span>Test</span>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
    <script src="js/three.js"></script>
    <script>
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.1, 1000 );
        camera.position.y = 24;

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

        var diameter = 20;
        var geometry = new THREE.CylinderGeometry( diameter, diameter, 15, 32 );

        var texture1 = new THREE.TextureLoader().load( 'images/image1.jpg' );
        var texture2 = new THREE.TextureLoader().load( 'images/image2.jpg' );
        var texture3 = new THREE.TextureLoader().load( 'images/image3.png' );

        texture1.wrapS = THREE.RepeatWrapping;
        //texture.wrapT = THREE.RepeatWrapping;
        //texture.repeat.set( 1, 4 );

        var materials = [];
        materials.push(new THREE.MeshBasicMaterial({ map: texture1 }));
        materials.push(new THREE.MeshBasicMaterial({ map: texture2 }));
        materials.push(new THREE.MeshBasicMaterial({ map: texture3 }));

        var cylinder = new THREE.Mesh( geometry, materials );
        cylinder.position.y = 25;
        scene.add( cylinder);

        camera.position.z = 40;


        function render() {
            requestAnimationFrame(render);
            //cylinder.rotation.z += 0.05;
          cylinder.rotation.y += 0.005;
            renderer.render(scene, camera);
        }
        render();
    </script>
</body>

Answer №1

If you're looking to add multiple textures to your cylinder, there's a simple solution that doesn't involve merging them into a single texture. You can render three cylinder wedges, each with its own unique texture. Here's an example of how you could achieve this:

var group = new THREE.Group();
scene.add( group );

var geometry = new THREE.CylinderBufferGeometry( 5, 5, 10, 16, 1, false, 0, 2 * Math.PI / 3 ); // Define a 1/3 cylinder wedge

var endCapMaterial = new THREE.MeshBasicMaterial();

// Create and position the meshes
mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture1 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 0, 0 );
group.add( mesh );

mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture2 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 2 * Math.PI / 3, 0 );
group.add( mesh );

mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture3 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 4 * Math.PI / 3, 0 );
group.add( mesh );

This code snippet is compatible with three.js version r.89.

Answer №2

One alternative method involves assigning textures to each face of your geometry by utilizing the geometry.faces[i].materialIndex property. In this scenario, it's crucial to ensure that the number of radial segments is divisible by three (for instance, when dealing with 3 textures).

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>
<html>
<head>
    <title>Creating a three.js application</title>
    <style>
        body { margin: 0; overflow:hidden;}
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
<script>
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.1, 1000 );
    camera.position.y = 24;

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

    var diameter = 20;
    var radialSegments = 33;
    var geometry = new THREE.CylinderGeometry( diameter, diameter, 15, radialSegments );
    
    var img1 = "http://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX9108127.jpg";
    var img2 = "http://d2gg9evh47fn9z.cloudfront.net/thumb_COLOURBOX8923432.jpg";
    var img3 = "http://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX19377428.jpg";

    var texture1 = new THREE.TextureLoader().load( img1 );
    var texture2 = new THREE.TextureLoader().load( img2 );
    var texture3 = new THREE.TextureLoader().load( img3 );

    THREE.DefaultLoadingManager.onLoad = function () {
        var materials = [];
        materials.push(new THREE.MeshBasicMaterial({ map: texture1 }));
        materials.push(new THREE.MeshBasicMaterial({ map: texture2 }));
        materials.push(new THREE.MeshBasicMaterial({ map: texture3 }));
        var l = geometry.faces.length;
        for (var i = 0; i < l; i++) {
            if (geometry.faces[i].normal.y !== 0) {
                // these are caps
                geometry.faces[i].materialIndex = 0;
            } else {
                // each segment has 2 faces
                geometry.faces[i].materialIndex = Math.floor(i * 3 / (radialSegments * 2));
            }
        }

        var cylinder = new THREE.Mesh( geometry, materials);
        cylinder.position.y = 25;
        scene.add( cylinder);

        camera.position.z = 40;

        function render() {
            requestAnimationFrame(render);
            cylinder.rotation.y += 0.005;
            renderer.render(scene, camera);
        }
        render();
    }
</script>
</body>

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

Prevent cross-site scripting (XSS) when using vue toasted for displaying notifications

Whenever I include js code like "><img src=1 onerror=prompt(document.cookie);> in an input field and click submit, I use vue-toasted. The notification appears as shown in this image: https://i.sstatic.net/Gju9h.jpg and a popup shows the cookie in ...

Could the THREE.raycaster be utilized for implementing enemy AI?

As a beginner in THREE, I've been exploring the three.js example of controllable MD2 characters to transform it into a 3rd person shooter game. Developing an algorithm for the enemy characters, I believe ray-casting would be most effective. The goal i ...

Executing an Ajax SPARQL request in Firefox

I've been attempting to run an asynchronous Ajax sparql query on dbpedia using Firefox, but I encountered a strange issue that I can't seem to figure out. Surprisingly, the query works perfectly fine in Chrome, Edge, and Internet Explorer, but wh ...

Exploring the colors of legend navigation icons in Google Pie charts

Is there a way to customize the color of the navigation links in Google pie charts (specifically the blue text in the bottom right corner)? https://i.sstatic.net/Hk591.png ...

Fresh React framework

I haven't worked on a React app in a while, but when I decided to start a new one and import my old function, I encountered the following error: C:/Users/Hello/Documents/Dev/contacts/client/src/App.tsx TypeScript error in C:/Users/Hello/Documents/Dev ...

Various materials including point cloud material and line basic material

When it comes to drawing a line with two vertices [10,10,0] and [-10,-10,0], I have successfully created the line with the following code: var geometry = new THREE.Geometry(); geometry.vertices.push(new THREE.Vector(10,10,0)); geometry.vertices.push(new T ...

Unable to trigger jQuery .post() function

I'm currently facing an issue with my AJAX call using jQuery. Here is the code snippet: // var upload = some JSON data $.post('/videos/upload', upload); Additionally, I have this express.js API segment to handle the request: app.post(&apo ...

What is the process for retrieving information from a retail outlet?

How can I retrieve data from the Vuex store using Vue.js? Below is my code: Vue.use(Vuex); export default new Vuex.Store({ modules: { data } }) data.js import axios from 'axios'; const state = { data: '' }; cons ...

How can I extract the URL from the event listener in Cordova's in-app browser event and then automatically close it once a specific URL is reached?

In my journey with ionic version 1 (just starting out with ionic & angularjs), I encountered an issue while trying to close the in app browser upon reaching a specific URL. The problem arises from the fact that the event triggered on "loadstart" is o ...

Do not forget to implement Array.find when working with the useSWR hook in Next.js

I have the following code: const fetcher = (url: string) => axios.get(url).then((r) => r.data); const {data} = useSWR("api/data", fetcher, {refreshInterval: 10000}) console.log(data.find(d => d.id === "123")) The API path is ...

Move the focus to the previous input field by removing the key

I have created a phone number input with 10 fields that automatically skip to the next field when you fill in each number. However, I would like to be able to go back to the previous field if I make a mistake and need to delete a digit. How can I achieve ...

Tips for closing a sidecart by clicking outside of it

I am currently exploring how to implement the functionality of closing my sidecart when I click outside of it. Below is the script I am using: const toggler = document.getElementById('menu-toggle'); const cartWrapper = document.getElementById( ...

Issue encountered when trying to display a view in Laravel using PHP

tag, I have implemented a search field in my master blade, integrating the TypeAhead autocomplete plugin. Below are the routes used for this functionality: Route::get('search',array('as'=>'search','uses'=>&apo ...

Trigger route handlers on both, successful authentication and failure, when using passport.js with a Node.js and Express.js REST API

Check out this simple login/token process using passport basic strategy for a Rest API: The Route: router.get('/token', authenticate.basic, controller.token); Authenticate Basic Strategy: authenticate.basic = passport.authenticate('basic ...

The close icon in the ReactStrap modal is not being displayed properly, and I need to know how to utilize the header with a different tag

I recently started working with React JS and I am currently utilizing the Modal component from reactStrap. <Modal isOpen={props.isOpen} centered='true'> <ModalHeader> Change this Question? <button type= ...

What is the best way to convert the response from an XMLHttpRequest to a JavaScript array and display it

Looking to transform the data from xmlhttp.responseText into a JavaScript array I have this {"name":"Eswara Manikanta Varma","email":"contact@email.com","mobile":"9966578911"} retrieved from xmlhttp.responseText, and now I need to convert it into a JavaSc ...

Tips for using ng-repeat in AngularJs to filter (key, value) pairs

I am trying to achieve the following: <div ng-controller="TestCtrl"> <div ng-repeat="(k,v) in items | filter:hasSecurityId"> {{k}} {{v.pos}} </div> </div> Code snippet for AngularJs: function TestCtrl($scope) { ...

Transfer an HTML file object between two <input type="file"> elements

I am looking to integrate a multi-file uploader into a form that allows users to prioritize the files they upload using draggable and sortable jQuery tools. One way I have added a multi-file input is: <input type = "file" multiple> When I select m ...

What is the best method for calculating the total of a column field within an array in Angular 9.1.9?

I am using Angular 9.1.9 and Html to work with a nested array field in order to calculate the total sum and display it in a row. Within my array list ('adherant'), I am aiming to sum up a specific column's values ({{ Total Amount }}) and pr ...

Personalizing the arrow positioning of the Angular8 date picker (both top and bottom arrow)

I am interested in enhancing the design of the Angular 8 date picker by adding top and bottom arrows instead of the default left and right arrows. Can someone guide me on how to customize it? Check out the Angular 8 date picker here ...