Dragonseer
Dragonseer

Reputation: 2874

Map a Canvas 2D to Three.js Canvas

I have a simple 2D game that I am building with Three.js. I only use the worlds X and Y position to move objects around, leaving their z position at zero. I use TrackballControls with rotation disable to allow 2D movement of the camera using the right click and zoom using the mouse wheel. I now have a need to implement fog of war for this game. After looking around, I've found that using a second canvas with a 2D context is the most convenient way to do this.

The challenge that this creates is that the Canvas 2D has to pan and zoom at the same rate that the 3D Canvas moves to have the fog placed over the correct items. I've managed to accomplish the panning by unprojecting the origin, but I am unsure how to accurately duplicate the zoom.

    var widthHalf = this.width / 2, heightHalf = this.height / 2;

    var origin = new THREE.Vector3();
    var projector = new THREE.Projector();
    origin = projector.projectVector(new THREE.Vector3(0, 0, 0), this.camera);
    origin.x = (origin.x * widthHalf) + widthHalf;
    origin.y = -(origin.y * heightHalf) + heightHalf;

    canvas2D.save();
    canvas2D.translate(origin.x, origin.y); //This works great

    canvas2D.scale(???,???); //Map to the zoom/position of the Three.js camera?

    //Do fog drawing here...

    //A 1x1 Rectangle for Scale - Should Map to a 1x1 square of Three.js space
    canvas2D.fillStyle = "#FF0000";
    canvas2D.fillRect(0, 0, 1, 1);

    canvas2D.restore();

Q: How do I map the distance of a Three.js camera to the scale of a Canvas 2D so that they both zoom at the same rate?


Upvotes: 3

Views: 1455

Answers (1)

Dragonseer
Dragonseer

Reputation: 2874

Found the solution. Answer is to do some math to determine the screen size of a 1x1 square of Three.js space and scale the canvas using that.

this.WorldtoPixel = function(worldPos)
{
    var widthHalf = this.width / 2, heightHalf = this.height / 2;

    var position = new THREE.Vector3();
    var projector = new THREE.Projector();
    position = projector.projectVector(worldPos, this.camera);
    position.x = (position.x * widthHalf) + widthHalf;
    position.y = -(position.y * heightHalf) + heightHalf;

    return position;
}

var origin = this.WorldtoPixel(new THREE.Vector3(0, 0, 0));
var onezero = this.WorldtoPixel(new THREE.Vector3(1, 0, 0));
var zeroone = this.WorldtoPixel(new THREE.Vector3(0, 1, 0));

var scaleX = onezero.x - origin.x;
var scaleY = origin.y - zeroone.y;
fogContext.scale(scaleX, scaleY);

Upvotes: 1

Related Questions