Creating a multitude of cubes by iterating through the pixel color data of getImageData in Three.js

Using a simple 3x3.png file to extract color/opacity data from, where each of the 9 pixels represents a different color/opacity level.

The .png is supposed to be loaded onto an off-screen canvas, following which the 9 cubes are drawn in a 3x3 grid pattern.

Although it seems like it's almost working, there must be something amiss in the implementation.

<!DOCTYPE html>
<head>
<title>Rendering cubes based on pixel values from a png</title>
<style>body {margin: 0px;background-color: #99F;overflow: hidden;}</style>
<script src="js/three.min.js"></script>
</head>
<body>

<!-- Pre-loading the 3x3 png image -->
<img id='image1' src='3x3.png' onload="javascript:loaded();">
<canvas id='canvas'></canvas>


<script>
    function loaded(){

    var img = new Image();
    img.src = document.getElementById("image1").src;
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.drawImage(img, 0, 0);

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    camera.position.z = 5;
    var geometry = new THREE.BoxGeometry( 1, 1, 1 );

    for (ix = 0; ix < img.width; ix++) { 
        for (iy = 0; iy < img.height; iy++) { 
            // get next pixel data
            var data = ctx.getImageData( ix, iy, 1, 1 ).data;
            var floats = data.slice( 0, 4 ).map( function( val ) { return val / 255; });
            var computedcolor = THREE.Color( floats[0], floats[1], floats[2] );
            var computedopacity = floats[4];

            var material = new THREE.MeshBasicMaterial( { color: computedcolor, opacity: computedopacity, side: THREE.DoubleSide } );
            var cube = new THREE.Mesh( geometry, material );
            scene.add( cube );
            cube.position.x = ix; //move the cube positions to rebuild the image using cubes instead of pixels
            cube.position.y = iy;
        }
    }

    var render = function () {
        requestAnimationFrame( render );
        camera.position.z = camera.position.z + .01;
        renderer.render(scene, camera);
    }
    render();
    }
</script>
</body>
</html>

Answer №1

Instead of using floats[4], consider using floats[3] for var computedopacity.

However, rather than trying to pinpoint the exact issue, I have written a code snippet that accomplishes the task you are attempting:

function createImageBoxes( image ) {

    // 2D

    var canvas = document.createElement( 'canvas' );
    canvas.width = image.width;
    canvas.height = image.height;

    var context = canvas.getContext( '2d' );
    context.drawImage( image, 0, 0 );

    var data = context.getImageData( 0, 0, canvas.width, canvas.height ).data;

    // 3D

    var group = new THREE.Group();
    var geometry = new THREE.BoxGeometry( 1, 1, 1 );

    for ( var i = 0, j = 0; i < data.length; i += 4, j ++ ) {

        var color = new THREE.Color();
        color.fromArray( data, i );
        color.multiplyScalar( 1 / 255 );

        if ( color.getHex() === 0 ) continue;

        var material = new THREE.MeshBasicMaterial( {
            color: color,
            wireframe: true,
        } );
        var mesh = new THREE.Mesh( geometry, material );
        mesh.position.x = j % canvas.width;
        mesh.position.y = - Math.floor( j / canvas.width );
        group.add( mesh );

    }

    return group;

}

//

var camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.x = 15;
camera.position.y = -10;
camera.position.z = 80;

var scene = new THREE.Scene();

var image = new Image();
image.addEventListener( 'load', function () {
    var group = createImageBoxes( image );
    scene.add( group );
    renderer.render( scene, camera );
} );
image.src = '../img/logo.png';

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

http://jsfiddle.net/44mj229c/

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

Despite functioning properly when triggered from the debug console, the jQuery AJAX request fails to work upon page load

The issue was resolved by disabling asynchronous requests in jQuery. Here is the Javascript & AJAX request (using jQuery) code on my page: "use strict"; var hsArea, counter, hotspots, count; counter = 4; count = 0; hotspots = {}; function fetchHots ...

Using ExpressJS and Jade to submit a form using the POST method and redirecting to a specified path

I am exploring node, express and jade for the first time and working on a small application that requires users to enter their name and password in a form. The app then redirects them to a path based on their username. Here is the code snippet to achieve ...

Implementing a Vue.js v-bind:style attribute onto a dynamically generated element post-page initialization

Let me start by explaining my current issue and dilemma: I have been tasked with converting an existing JS project into a Vue.js framework. While I could easily solve a particular problem using jQuery, it seems to be posing quite a challenge when it comes ...

Tips for enhancing the transition effect of animated gifs on a webpage using JavaScript

In my code, I have an interval set to run every seven seconds. Within this interval, there are two gifs that each last for seven seconds. My goal is to display one of the gifs in a div (referred to as "face") based on certain conditions - for example, if t ...

Learn how to properly convert a string into a valid URL using the Next JS router when pushing pages

I'm dealing with a string that looks like this: /dashboard/products/:id. My goal is to utilize Next Js's router to navigate to that URL and replace the placeholder :id with an actual id. Here's the code I've written: {products.map(prod ...

Using both PHP and jQuery to add a class upon changing the URL

I am struggling to implement sorting functionality on my webpage, as the active class is not being added to the selected sorting option... Check out my code snippet below: <ul class="nav nav-tabs"> <li class="menusel active" name="hlavni" on ...

Autofill with JavaScript - Dynamic Form Population

Looking to create a form-based HTML page. The objective is to have the second input box automatically populate based on the user's input in the first input box. I've gone through various guides and tried to implement this script, but it doesn&ap ...

What is the best way to leverage command line arguments with AngularJS Protractor?

Currently, I am utilizing Protractor for executing extensive end-to-end tests. Instead of storing login credentials in a spec file, I am keen on passing them through the command line. Upon stumbling across a post showcasing the usage of process.argv.forEac ...

Leveraging an Array of Objects in JavaScript

Need help with my JavaScript code! I want to adjust the date in a Date object by adding specific days and then save it. Here is what I have so far: let orderIdDateCorrectionDict = [ { "orderId": "2020053100", "dayCorrection": -146 }, { "orderId" ...

What is the best way to automatically insert data into a database at regular intervals, while ensuring that users are unable to manipulate the timing through inspect

Is there a secure way to insert 1 point into the database every x seconds without allowing users to manipulate the interval time through inspect element? var time = 1; var interval = setInterval(function() { if (time != time + 1) { ...

Steps to create an automatic submission feature using a combobox in HTML5 and then sending the retrieved data back to the HTML file

Here is the code snippet I've been working on: <strong>Station Name</strong> <!--This portion includes a combobox using HTML5 --> <input type=text list=Stations> <datalist id=Stations> <option>Station1</opt ...

Confirming user banking information is necessary solely for account activation through Stripe

I've been working with NodeJS and ExpressJS Is there a way to set up account verification with Stripe? I want to confirm that users have bank accounts without charging them. What kind of information can I access through this verification process? My ...

I am currently attempting to find a color picker element within a parent class using Cypress CSS Locator. While I am able to reach the parent element, I am unsure of the correct method to target the

My user interface has a list of elements displayed in 2 columns. The first column shows the name of the item, such as Manager, Operator, and the list is expected to grow. The second column consists of a color picker element where you can choose a color. I ...

Remove duplicate elements from a JSON array

How can I add each item in an array for each duplicate? Transform: [ { "uuid":"EE877ABD-932F-4B4C-AB23-B324363B0B60", "planning":[ { "uuid":"6D680178-9B05-4744-A004-163D4B3E1E84", "star ...

having trouble with my lambda function reading the basic json object

I recently joined Lambda and have been attempting to create a simple JSON object. However, I keep encountering an error that says "parsing error, unexpected token." Here is my code, which I have verified to be valid JSON: { "metadata": { ...

Is there a Webpack plugin available that can analyze the usage of a function exported in a static

Just to clarify, I am presenting this theoretical scenario on purpose, as it reflects a genuine issue that I need to solve and am uncertain if it's feasible. Imagine I have a JavaScript package named road-fetcher, containing a function called find wh ...

invoking a method of the grandparent from within the grandchild component

My components are nested three levels deep: <GrandParent /> <Parent /> <Child /> In the Child component, I have a button that, when double clicked, should call a function in the GrandParent component. <button @dblclick=&quo ...

Create a dynamic animation page using Node.js, then seamlessly redirect users to the homepage for a smooth user

Good day everyone! I've decided to change things up with my latest query. I'm currently working on adding a loading page animation that will show for 3 seconds when visiting the '/' route, and then automatically redirect to the home pag ...

Encountering an error while attempting to merge webgl_interactive_cubes with pointer lock in three.js: "Unable to access properties of undefined (reading 'getHex')."

I’m in the process of developing a scene with walk-navigation and interactive objects for educational purposes. To achieve this, I am utilizing the Pointer Lock Control example for walk navigation and the interactive cubes example from three.js. The proj ...

What is the proper way to utilize --legacy-peer-deps or enforce in a vite build?

I encountered an issue with a package called react-typed in my project. To install it, I had to use --legacy-peer-deps. When deploying, I need to use vite build. However, when I run the command, I receive the following errors: 8:59:31 AM: npm ERR! node_mo ...