Billy Vivian
Billy Vivian

Reputation: 41

JavaScript binary operators

Working on a WebGL project and I am looking over code from a class example. In one of the loops this code was given:

var c = (((i & 0x8) == 0) ^ ((j & 0x8)  == 0));

The variables i and j go up to a certain value in a for loop. What does this statement mean? Does this make sure that the variable c is in hexadecimal form?

var texSize = 64; 
var image1 = new Array(); 
for (var i =0; i<texSize; i++) 
    image1[i] = new Array(); 
for (var i =0; i<texSize; i++) 
    for ( var j = 0; j < texSize; j++) 
        image1[i][j] = new Float32Array(4); 
for (var i =0; i<texSize; i++) 
    for (var j=0; j<texSize; j++) 
    { 
        var c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)); 
        image1[i][j] = [c, c, c, 1]; 
    }

Upvotes: 4

Views: 193

Answers (2)

user128511
user128511

Reputation:

SMchrohan's answer is correct. The code is basically making a checkerboard texture.

The ?? & 0x8 means it that expression will be true when bit 3 (0,1,2,3) is true. bit 3 in binary is true every other set of 8 values (0-7 it's false, 8-15 it's true, 16-23 it's false, etc).

Then the code takes the opposite of that with == 0.

It does it for both i and j.

The ^ means exclusive-or which is true when both parts are the different (true, false or false, true) and false when they are both the same (false, false, or true, true). Because ^ is a bitwise operator both values are first converted to integers so false becomes 0 and true becomes 1. The 2 int values then have their bits exclusive-ored so

0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
1 ^ 1 = 0

that means each entry in image1 is either [0, 0, 0, 1] or [1, 1, 1, 1]

here's some code to plot it

var texSize = 64; 
var image1 = new Array(); 
for (var i =0; i<texSize; i++) 
    image1[i] = new Array(); 
for (var i =0; i<texSize; i++) 
    for ( var j = 0; j < texSize; j++) 
        image1[i][j] = new Float32Array(4); 
for (var i =0; i<texSize; i++) 
    for (var j=0; j<texSize; j++) 
    { 
        var c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)); 
        image1[i][j] = [c, c, c, 1]; 
    }

// lets plot it

var ctx = document.createElement("canvas").getContext("2d");
document.body.appendChild(ctx.canvas);
ctx.canvas.width = texSize;
ctx.canvas.height = texSize;

for (var i =0; i<texSize; i++) 
    for (var j=0; j<texSize; j++) 
    { 
        var c = image1[i][j][0]
        ctx.fillStyle = c ? "red" : "yellow";
        ctx.fillRect(i, j, 1, 1);
    }
canvas { border: 1px solid black; }
<body></body>

Note that the code doesn't appear to make much sense. It says texSize so it seems to be making a texture but it's making one Float32Array per pixel (the line that says)

image1[i][j] = new Float32Array(4);

and then it's replacing each of those individual Float32Arrays with a JavaScript native array on this line

image1[i][j] = [c, c, c, 1]; 

Which makes the Float32Array line useless.

On top of that I have no idea what an array or arrays of 1 pixel Float32Arrays is good for. You can't upload it like that to WebGL.

Normally I'd make one Uint8Array for the entire texture like this

var texSize = 64; 
var pixels = new Uint8Array(texSize * texSize * 4);

for (var i =0; i<texSize; i++)  {
    for (var j=0; j<texSize; j++) { 
        var c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)); 
        var p = c ? 255 : 0;
        var offset = (i * texSize + j) * 4;
        pixels[offset + 0] = p;  // red
        pixels[offset + 1] = p;  // green
        pixels[offset + 2] = p;  // blue
        pixels[offset + 3] = 255;// alpha
    }

}

Or I'd use the 2D canvas API to make the texture

without some context though I don't know what the final purpose of the code is.

Upvotes: 2

S McCrohan
S McCrohan

Reputation: 6693

& is bitwise and.

^ is bitwise xor.

0x8 is the hex expression of the integer 8.

c will be 1 if either i or j BUT NOT BOTH have a 1 in their 4th bit - that is, a bitwise and with 0x8 (binary 1000) returns 0.

To walk through this a little more:

i & 0x8 will return either 0 (if the value of i has a 0 in bit 4) or 8 (if it has a 1 in that position).

(i & 0x8) == 0 will be either true or false.

(((i & 0x8) == 0) ^ ((j & 0x8) == 0)) will be 1 if either ((i & 0x8) == 0) or ((j & 0x8) == 0) is true, or 0 if both are false OR both are true.

Upvotes: 1

Related Questions