0

I adapted an old three.js code for my application. It's a 3d function with axes grids. I added two numbers for x axis as test:

https://jsfiddle.net/cjfwg2c4/

Code works perfectly for old revision 62 of three.js. I tried to adapt it to the latest revision, r74:

https://jsfiddle.net/nwLLq8q1/

The problem is that, without THREE.SpriteAlignment.topLeft, sprites are aligned at center by default.

rev 62:

var spriteAlignment = THREE.SpriteAlignment.topLeft;
var spriteMaterial = new THREE.SpriteMaterial({ 
    map: texture, 
    useScreenCoordinates: false, 
    alignment: spriteAlignment,
});

rev 74:

var spriteMaterial = new THREE.SpriteMaterial({ map: texture});

THREE.SpriteAlignment was removed from revision 63.

The effect is that the numbers near the grid apparently move inside and outside the grid when you rotate the camera. You can read this page for more detailed informations.

How can I obtain the same effect of THREE.SpriteAlignment.topLeft with the latest three.js?

Marco Sulla
  • 15,299
  • 14
  • 65
  • 100

1 Answers1

0

Thanks to Westlangley's comment

Just draw your text in the center of the canvas. That should work for your purposes

I solved it. IMHO my code now works better than the original one.

Fiddle:

https://jsfiddle.net/57hj1f4m/2/

Code:

function toBinaryInt(num) {
    /**
     * @author fernandosavio
     * http://stackoverflow.com/a/16155417/1763602
     */
    
    "use strict";
    
    return (num >>> 0).toString(2);  // jshint ignore:line
}


function getNextPowerOfTwo(num) {
    /**
     *  @author Marco Sulla (marcosullaroma@gmail.com)
     *  @date Feb 17, 2016
     */
    
    "use strict";
    
    if (num < 0) {
        throw new Error("Argument must be positive");
    }
    
    var bin_str = toBinaryInt(num - 1);
    
    if (bin_str.indexOf("0") < 0 || bin_str === "0") {
        return num;
    }
    else {
        return Math.pow(2, bin_str.length);
    }
}

function adaptCanvasToText(canvas, message, font_size, font_face) {
    /**
     *  @author Marco Sulla (marcosullaroma@gmail.com)
     *  @date Feb 17, 2016
     */
    
    "use strict";
    
    var context = canvas.getContext('2d');
    
    if (canvas.height > canvas.width) {
        canvas.width = canvas.height;
    }
    
    
    while (true) {
        var side = getNextPowerOfTwo(canvas.width);
        
        if (side < 128) {
            side = 128;
        }
        
        canvas.width = canvas.height = side;
        
        context.font = "Bold " + font_size + "pt " + font_face;
        
        var metrics = context.measureText(message);
        var text_width = metrics.width;
        var text_side = getNextPowerOfTwo(Math.max(text_width, font_size));
        
        if (text_side >= 128) {
            if (side !== text_side) {
                canvas.width = text_side;
                continue;
            }
        }
        else if (side !== 128) {
            canvas.width = 128;
            continue;
        }
        
        break;
    }
}


function makeTextSprite(message, opts) {  // jshint ignore:line
    /**
     *  @author Lee Stemkoski
     *  @author Marco Sulla (marcosullaroma@gmail.com)
     *  
     *  https://stemkoski.github.io/Three.js/Sprite-Text-Labels.html
     *  
     */
    
    "use strict";
    
    if ( opts === undefined ) {
        opts = {};
    }
    
    var possible_opts = ["font_face", "font_size", "border_thickness", 
                         "border_color", "background_color", "text_color"];
    
    for (var k in opts) {
        if (opts.hasOwnProperty(k)) {
            if (possible_opts.indexOf(k) < 0) {
                throw new Error("Unknown option '" + k.toString() + "'");
            }
        }
    }
    
    if (opts["font_face"] === undefined) {
        opts["font_face"] = "Arial";
    }
    
    if (opts["font_size"] === undefined) {
        opts["font_size"] = 100;
    }
    
    var font_size = opts["font_size"];
    
    if (font_size <= 0) {
        throw new Error("'font_size' must be a positive number");
    }
    
    if (opts["border_thickness"] === undefined) {
        opts["border_thickness"] = 0;
    }
    
    if (opts["border_thickness"] < 0) {
        throw new Error("'border_thickness' must be >= 0");
    }
    
    if (opts["border_color"] === undefined) {
        opts["border_color"] = { r:0, g:0, b:0, a:1.0 };
    }
    
    if (opts["background_color"] === undefined) {
        opts["background_color"] = { r:255, g:255, b:255, a:1.0 };
    }
    
    if (opts["text_color"] === undefined) {
        opts["text_color"] = { r: 0, g: 0, b: 0, a: 1 };
    }
    
    var border_color = opts["border_color"];
    var background_color = opts["background_color"];
    var text_color = opts["text_color"];
    
    var sprite_align;
    
    if (old) {
      sprite_align = THREE.SpriteAlignment.topLeft;
    }
        
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    
    adaptCanvasToText(canvas, message, font_size, opts["font_face"]);
    
    var scale;
    
    if (canvas.width > 128) {
        scale = canvas.width / 128;
    }
    
    // background color
    context.fillStyle   = ("rgba(" + background_color.r + "," + 
                           background_color.g + "," + background_color.b + "," + 
                           background_color.a + ")");
    // border color
    context.strokeStyle = ("rgba(" + border_color.r + "," + border_color.g + 
                           "," + border_color.b + "," + border_color.a + ")");

    context.lineWidth = opts["border_thickness"];
    // 1.4 is extra height factor for text below baseline: g,j,p,q.
    
    // text color
    context.fillStyle = ("rgba(" + text_color.r + "," + text_color.g + 
                           "," + text_color.b + "," + text_color.a + ")");
    
    var metrics = context.measureText( message );
    var text_width = metrics.width;
    
    console.log(text_width);

    context.fillText( message, (canvas.width - text_width) / 2, canvas.height / 2 + font_size / 2);
    
    // canvas contents will be used for a texture
    var texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;
    
    var spriteMaterial;
    
    if (old) {
        spriteMaterial = new THREE.SpriteMaterial({
            map: texture, 
            useScreenCoordinates: false, 
            alignment: sprite_align,
        });
    }
    else {
        spriteMaterial = new THREE.SpriteMaterial({map: texture});
    }
    
    var sprite = new THREE.Sprite(spriteMaterial);
    
    if (scale) {
        sprite.scale.set(scale, scale, 1);
    }
    
    return sprite;  
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Marco Sulla
  • 15,299
  • 14
  • 65
  • 100