Guide to loading a Canvas texture in a Wavefront OBJ using three.js

Hello there! I am currently working on a project where I am using three.js to display an obj file exported from Blender and map a texture from a canvas onto it. I managed to successfully display the image in obj format, but when I tried to apply the canvas texture to the obj model, the model turned black. I also attempted to convert the canvas to an image using toDataURL and then map it, but that also did not work. I would greatly appreciate any assistance on this matter.

  function convertCanvasToImage(ele) {

    var image = new Image();
    image.src = ele.toDataURL("image/png");
    return image;
  }

  function changeCanvas() {

    canvas = document.getElementById('canvas_id'),
    ctx = canvas.getContext('2d');
    ctx.font = '20pt Arial';
    ctx.fillStyle = 'red';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'white';
    ctx.fillRect(10, 10, canvas.width - 20, canvas.height - 20);
    ctx.fillStyle = 'black';
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(new Date().getTime(), canvas.width / 2, canvas.height / 2);
    image_t = convertCanvasToImage(canvas);
    return image_t;
}

    function init() {

        container = document.createElement('div');
        document.body.appendChild(container);

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
        camera.position.z = 250;

        // scene
        scene = new THREE.Scene();
        scene.background = new THREE.Color( 'red' );

        var ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
        scene.add(ambientLight);

        var pointLight = new THREE.PointLight(0xffffff, 0.8);
        camera.add(pointLight);
        scene.add(camera);

        // manager

        function loadModel() {

            object.traverse(function (child) {

                if (child.isMesh) child.material.map = texture;

            });

            object.position.y = -95;
            scene.add(object);

        }

        var manager = new THREE.LoadingManager(loadModel);

        manager.onProgress = function (item, loaded, total) {

            console.log(item, loaded, total);

        };

        // texture
    // texture = new THREE.Texture(canvas); //it's my initial try,but it didn't work

    var textureLoader = new THREE.TextureLoader();
    texture = textureLoader.load("three.js-master/examples/models/obj/clothes/426_con.png");//this works!!!
    // img = changeCanvas()
    texture = textureLoader.load(image_t);//but this doesn't work!!!


        // model
        function onProgress(xhr) {
            if (xhr.lengthComputable) {
                var percentComplete = xhr.loaded / xhr.total * 100;
                console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
            }
        }

    function onError() {
    }

    var loader = new THREE.OBJLoader(manager);

    loader.load('three.js-master/examples/models/obj/clothes/426_con.obj', function (obj) {

        object = obj;
    }, onProgress, onError);

    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);

    function animate() {
        requestAnimationFrame(animate);
        camera.lookAt(scene.position);
        changeCanvas();
        texture.needsUpdate = true;
        renderer.render(scene, camera);
    }

I am curious to know if there is a way in three.js to directly texture a canvas onto an obj file without needing any additional translations?

Answer №1

My expertise in JS is quite lacking, and I must admit, I can be quite careless at times. A big shoutout to gman and manthrax for being incredibly helpful. Their answers have really helped me stay calm and analyze the problem at hand. While most Three.js Canvas texture examples I've come across are for geometry textures, it's worth noting that it's also possible for obj textures. Surprisingly, the texture generated by the canvas appears no different from a regular image texture.

<script>
    var container;
    var camera, scene, renderer, texture, canvas;
    var object;

  function changeCanvas() {
    canvas = document.getElementById('canvas_id');
    ctx = canvas.getContext('2d');
    img = new Image();
    img.onload = function(){ctx.drawImage(img, 0, 0)};
    img.src = "../assets/UV.png";//img address
  }

    function init() {

        container = document.createElement('div');
        document.body.appendChild(container);

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
        camera.position.z = 250;

        // scene
        scene = new THREE.Scene();
        scene.background = new THREE.Color( 'black' );

        var ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
        scene.add(ambientLight);

        var pointLight = new THREE.PointLight(0xffffff, 0.8);
        camera.add(pointLight);
        scene.add(camera);

        // manager

        function loadModel() {
            object.traverse(function (child) {
                if (child.isMesh) child.material.map = texture;
            });
            object.position.y = -95;
            scene.add(object);
        }

        var manager = new THREE.LoadingManager(loadModel);
        manager.onProgress = function (item, loaded, total) {
            console.log(item, loaded, total);
        };

        //texture
    changeCanvas();
    texture = new THREE.CanvasTexture(canvas);

        // model
        function onProgress(xhr) {
            if (xhr.lengthComputable) {
                var percentComplete = xhr.loaded / xhr.total * 100;
                console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
            }
        }

    function onError() {}

    var loader = new THREE.OBJLoader(manager);

    loader.load('../assets/426.obj', function (obj) {
        object = obj;
    }, onProgress, onError);

    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);

  var controls = new THREE.OrbitControls( camera, renderer.domElement );
}

    function animate() {
      // changeCanvas();
      texture.needsUpdate = true;
      camera.lookAt(scene.position);
      renderer.render(scene, camera);
    requestAnimationFrame(animate);
    }

  init();
    animate();

</script>

Answer №2

Is the texture being created using THREE.CanvasTexture(yourCanvas)?

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 best way to send a 102 Processing status code in Express?

I'm in the process of configuring a new HTTP server to run a lengthy command and return the output of that shell command back to the client. Currently, I am using Express v4.17.1. However, requests from clients are consistently timing out when runnin ...

Trouble with clicking buttons in Java and Selenium web scraping

Hey everyone, Currently, I'm working on a Java Selenium script that automates clicking and filling forms for me. I've written a line of code that's causing me some trouble. The intention is to click on a button, but it's not happening ...

Is it possible in Javascript to trace the origins of a particular element's property inheritance for debugging purposes?

I'm currently dealing with an issue where the computed style font-size of a particular element is "16px". I've been attempting to pinpoint where in the CSS or JavaScript this font size setting is coming from, specifically within one of its parent ...

JavaScript: Searching for multiple parameters is not possible - when using asynchronous functions, only the first parameter is returned

I've been struggling with this issue for a whole day now: I'm working on a website where I can input contacts into a SQLite database. My goal is to be able to query the database by either studentID or last name (nachname in German). I have an API ...

Webpack is notorious for creating multiple copies of images

Having an issue with Webpack where it's generating duplicate images, one of which is broken. I have an original image image, and after running Webpack, two duplicates are created. One works fine: image, but the other one is broken: image. I'm us ...

Guide on how to receive multiple responses from a single ajax request in PHP

I am in the process of developing a web application that includes a search feature. When a user enters a name to search for, I use an AJAX request to retrieve and display records related to that specific person. However, due to the extensive amount of info ...

Why won't my JavaScript addEventListener activate on form submission?

I have a basic question as a beginner in JavaScript. I am facing some challenges with my first task involving JavaScript. I decided to learn JS by creating a TODO List, but I am stuck right at the beginning. The event listener that should respond when the ...

Is there a way to automatically add a div to the window as the user scrolls and then hide the div when they scroll back to the

Seeking assistance with creating a function that will add a 'sticky' class to the menu when the user scrolls down to the middle, and then append a div when the 'sticky' class is present. Currently facing issues where the div keeps appen ...

Combine two elements in an array

I am faced with a challenge in binding values from an Array. My goal is to display two values in a row, then the next two values in the following row, and so on. Unfortunately, I have been unable to achieve this using *ngFor. Any assistance would be greatl ...

Are Global variables supported in the EXT JS framework?

When working with Java and C++, it is common practice to store a variable globally so that its value can be accessed from anywhere within the project. For example, if I am working inside a class named Residence and saving an INT as the residenceNumber to a ...

Where to Find the Source File for three.js ColladaLoader

Recently, I delved into the world of 3D programming using Javascript. My journey led me to discover the fascinating THREE.js framework, which I have been experimenting with. After creating a Google Sketchup file (.skp), I decided to export it to Collada fo ...

Access nested objects in Javascript (Vue)

Struggling with a simple question as a beginner... I am dealing with an object of objects: monsters { place1: { monster1: { ... } monster2: { ... } } place2: { monster3: { ... } monster4: { ... } } } I ...

Troubleshooting angular radio input display issue caused by controller updates

When the page loads, my AngularJS controller.js initializes the scope model by fetching data from an AJAX response: services.InitializePage().then(function (response) { $scope.DataModel = response.data; Shortly after that, the model undergoes ...

Despite using Vue and Vuex with Axios asynchronously, the getters are still returning an empty array

I am encountering an issue with getters that are returning the initial state (an empty array). In my component, I have a method called created that sets the axios call result into the state. created() {this.$store.dispatch("SET_STORIES");}, I am using m ...

Explore our array of images displayed in an interactive gallery featuring clickable

I have a query I'm facing an issue with my code. Currently, I have a gallery that displays images perfectly. Now, I want to enhance it by showing a larger resolution of the image when clicked. However, when I add the href tag to link the images, they ...

What is the best way to reach the parent controller's scope within a directive's controller?

In a scenario where I have a custom directive nested inside a parent div with a controller that sets a variable value to its scope, like this: html <div ng-controller="mainCtrl"> <p>{{data}}</p> <myDirective oncolour="green" ...

JavaScript will continue to process the submit to the server even after validation has been completed

My current challenge involves implementing form validation using JavaScript. The goal is to prevent the form from being sent to the server if any errors are found. I have made sure that my JavaScript function returns false in case of an error, like so: ...

Deactivate the dependent picklist functionality on a Visualforce page

After successfully disabling all input and select elements on my page using the following code: $('input').prop('disabled',true); $('select').prop('disabled',true); I encountered an issue with two picklist fields i ...

Creating trails by following the cursor's movement in KineticJS

Currently, I am working on a drawing application using KineticJS. While I have successfully used it to draw shapes and straight lines by following the method outlined in KineticJS - Drawing Lines with Mouse, I now need to draw a line along the mouse's ...

What is the reason behind the inability of this YouTube instant search script to enable fullscreen mode?

Looking to implement a Youtube instant search on my website, I came across this script that seems ideal for my needs. However, I'm facing an issue where the iframe is not displaying the allowfullscreen property. Can anyone assist with this problem? Th ...