Emmanuel janssens
Emmanuel janssens

Reputation: 31

I want to map a bunch of planes onto a sphere it works but with some unexcpected bugs

I am currently working on a project for school where I have to make a sphere where I have to Map ~5000 images on it

I have here a flat projection from what I want to map
I have here a flat projection from what I want to map

And here I have a spherical model of it
And here I have a spherical model of it

I am using three.JS, and the principe of the mercator projection but as you can see Images rotate And I dont know how to fix that.

And I have been searching for a while and I found nothing

And here is the code I use to place all my images

drawMeridianCells(scene,rayon)
{
    var startCollPos = 5;
    var currentCounter = 0;
    var currentRow = 0;

    var counter = 0;


    let cell = new Array(this._totalCells);
    var rows = [4,3,4,4,6,6,6,6,4,4,3,4];
    var col = [2,4,6,8,10,12,12,10,8,6,4,2];
    var res = Number(col[counter]) * Number(rows[counter])  ;

    var currentIndex = 0;

    var north = true;


    for(var i = 0; i < this._totalCells; i++)
    {
        if(currentCounter >= col[counter])
        {       
            currentRow++;                                        
            currentCounter = 0;     
        }     


        if( currentIndex >= res)
        {           
            counter++;  
            res = Number(col[counter]) * Number(rows[counter])  ;                        
            currentIndex = 0;

            if(north)
                startCollPos--;
            else
                startCollPos++;

            if(startCollPos < 0)
            {
                startCollPos =0;
                north =  false;
            }
        }

        //spherical W/ mercator projection
        //https://stackoverflow.com/questions/12732590/how-map-2d-grid-points-x-y-onto-sphere-as-3d-points-x-y-z

        var long = (this._posX  +(currentCounter+startCollPos) * (this._celW+2))/rayon;
        var lat = 2*Math.atan(Math.exp(  (this._posY + (currentRow) * (this._celH*2))/rayon )) - Math.PI/2;

        var _x = rayon* (Math.cos(lat) * Math.cos(long)) ;
        var _y = rayon* (Math.cos(lat)  * Math.sin(long));
        var _z = rayon* (Math.sin(lat));

        cell[i] = new Square(new Point(_x,_y,_z ),
        this._celW  ,
        this._celH  );


        //flat
        /*cell[i] = new Square(   new Point((this._posX  +(currentCounter+startCollPos) * (this._celW)),
        (this._posY + (currentRow) * (this._celH)),0 ),
        this._celW,
        this._celH  );*/

        cell[i].drawSquare(scene,Math.random() *0xffffff);     
        cell[i].lookAtZero();

        currentCounter++;        
        currentIndex++;   

    }         
}

I hope I have been clear enough

Upvotes: 1

Views: 595

Answers (1)

Salix alba
Salix alba

Reputation: 7824

I think the problem might be in the Square constructor, or possibly in drawSquare(). The lookAtZero()` method is also likely to be suspect, I think this rotates the normal to point to zero but is ambiguous over quite how the shape is rotated to make this happen.

When you are constructing the squares you need to ensure one edge is along a line of latitude and one is along a line of longitude. Starting with

var x0 = rayon* (Math.cos(lat) * Math.cos(long)) ;
var y0 = rayon* (Math.cos(lat)  * Math.sin(long));
var z0 = rayon* (Math.sin(lat));

as the centre of the square. The horizontal tangent will be

tx = -Math.sin(long)
ty = Math.cos(long)
tz = 0

and the tangent along the line of latitude

ux = -Math.cos(lat) * Math.cos(long)
uy = -Math.cos(lat) * Math.cos(long)
uz = Math.sin(lat)

These are obtained by differentiating with respect to long and lat respectively. They should be unit length vectors.

You can then form a rectangle with point

x0 +/- celW * tx  +/-  celH * ux
y0 +/- celW * ty  +/-  celH * uy
z0 +/- celW * tz  +/-  celH * uz

The other way to do it would be to form points by incrementing the lat and long parameters

var x2 = rayon* (Math.cos(lat + lat_inc) * Math.cos(long + long_inc)) ;
var y2 = rayon* (Math.cos(lat + lat_inc) * Math.sin(long + long_inc));
var z2 = rayon* (Math.sin(lat + lat_inc));

this would give you a trapezium rather than a rectangle though.

Upvotes: 2

Related Questions