0

I've been trying to write a program that can render 4D lines, the specific function doing this gets the lines already rotated, and the function attempts to clip the lines at planes z = p and w = p if needed, and then draw the line to the screen.

I think that I am doing at least most of this properly, however I am unsure, and not having much experience viewing the fourth dimension I cannot tell what might be a visual bug, or what is actually how it should be rendered.

The function first loads a line into two variables, each is one of the two endpoints of the line. If both points are beyond clippl (the clipping plane variable) for z = clippl and w = clippl, it then applies perspective transformation to them, and subsequently renders a line on the screen correspondingly.

If certain logic is met for the points, the function goes through a process of clipping them, and then continues the same as it would outside the clipping planes.

The location of the camera is held in the variables Ox, Oy, Oz, Ow at the beginning of the full program.

I can't tell if I've done this properly, can anyone tell me if this works right as a 4D perspective projection from a first person camera?

EDIT: I've added points to the rendering list that are at the corners of the cube I'm rendering, and it seems to show that there is in fact some problem with the line clipping, as I am fairly certain that the points are rendering properly, and there is not always a line showing up at it. Could the problem have to do with the w = p clip?

Here's the function, the program uses p5.js:

function drawPLines(P){
  var lA,lB;
  
  for(var i=0;i<P.length;i++){
    lA = [P[i][0],P[i][1],P[i][2],P[i][3]];
    lB = [P[i][4],P[i][5],P[i][6],P[i][7]];
    //X: ( x*VS+(width*0.5)+(ox*VS) )
    //Y: ( y*VS+(height*0.5)+(oy*VS) )
    //x: (XV[0]*P[i][0])+(YV[0]*P[i][1])+(ZV[0]*P[i][2])+(WV[0]*P[i][3])
    //y: (XV[1]*P[i][0])+(YV[1]*P[i][1])+(ZV[1]*P[i][2])+(WV[1]*P[i][3])
    var x0,y0,x1,y1;
    //x0 = (XV[0]*lA[0])+(YV[0]*lA[1])+(ZV[0]*lA[2])+(WV[0]*lA[3]);
    //y0 = (XV[1]*lA[0])+(YV[1]*lA[1])+(ZV[1]*lA[2])+(WV[1]*lA[3]);
    
    //new rendering pipeline
    
    
    //old rendering pipeline
    if(lA[2]>clippl&&lB[2]>clippl&&lA[3]>clippl&&lB[3]>clippl){
    x0 = XV[0]*lA[0];
    y0 = YV[1]*lA[1];
    x0 = (x0/lA[3])/(lA[2]/lA[3]);
    y0 = (y0/lA[3])/(lA[2]/lA[3]);
    //console.log(y);
    x0 = ( x0*VS+(width*0.5)+(ox*VS) );
    y0 = ( y0*VS+(height*0.5)+(oy*VS) );
    
    //x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
    //y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
    x1 = XV[0]*lB[0];
    y1 = YV[1]*lB[1];
    x1 = (x1/lB[3])/(lB[2]/lB[3]);
    y1 = (y1/lB[3])/(lB[2]/lB[3]);
    //console.log(y);
    x1 = ( x1*VS+(width*0.5)+(ox*VS) );
    y1 = ( y1*VS+(height*0.5)+(oy*VS) );
    stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
    line(x0,y0,x1,y1);
    }else if((lA[2]>clippl||lA[3]>clippl||lB[2]>clippl||lB[3]>clippl)){
        
        var V = 0;
        var zV = 0;
        var wV = 0;
        //var oV = 0;
        
        if(lA[2]>clippl&&lA[3]>clippl){
            V++;
        }else if(lA[2]>clippl&&lA[3]<=clippl){
            zV++;
        }else if(lA[2]<=clippl&&lA[3]>clippl){
            wV++;
        }/*else{
            oV++;
        }*/
        
        if(lB[2]>clippl&&lB[3]>clippl){
            V++;
        }else if(lB[2]>clippl&&lB[3]<=clippl){
            zV++;
        }else if(lB[2]<=clippl&&lB[3]>clippl){
            wV++;
        }/*else{
            oV++;
        }*/
        
        if((V==1)||(wV==1&&(V==1||zV==1))||(zV==1&&(V==1||wV==1))){
        
        var lin = lB;
        var out = lA;
        if(lA[2]<=clippl){
            out = lB;
            lin = lA;
        }
        
        if(lin[2]<=clippl){
            lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[2]))/(lA[2]-lB[2]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[2]))/(lA[2]-lB[2]))+lB[1],clippl,((((lA[3]-lB[3])*clippl)-((lA[3]-lB[3])*lB[2]))/(lA[2]-lB[2]))+lB[3]];
        }
        
        if((lA[2]-lB[2])!==0){
            lA = lin;
            lB = out;
        }
        
        lin = lA;
        out = lB;
        
        if(lB[3]<=clippl){
            out = lA;
            lin = lB;
        }
        
        if(lin[3]<=clippl){
            lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[3]))/(lA[3]-lB[3]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[3]))/(lA[3]-lB[3]))+lB[1],((((lA[2]-lB[2])*clippl)-((lA[2]-lB[2])*lB[3]))/(lA[3]-lB[3]))+lB[2],clippl];
            //alert(lin);
            //alert(out);
        }
        
        if((lA[3]-lB[3])!==0){
            lA = lin;
            lB = out;
        }
        
        if(lA[2]>clippl||lB[2]>clippl||lA[3]>clippl||lB[3]>clippl){
        x0 = XV[0]*lA[0];
    y0 = YV[1]*lA[1];
    x0 = (x0/lA[3])/(lA[2]/lA[3]);
    y0 = (y0/lA[3])/(lA[2]/lA[3]);
    //console.log(y);
    x0 = ( x0*VS+(width*0.5)+(ox*VS) );
    y0 = ( y0*VS+(height*0.5)+(oy*VS) );
    
    //x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
    //y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
    x1 = XV[0]*lB[0];
    y1 = YV[1]*lB[1];
    x1 = (x1/lB[3])/(lB[2]/lB[3]);
    y1 = (y1/lB[3])/(lB[2]/lB[3]);
    //console.log(y);
    x1 = ( x1*VS+(width*0.5)+(ox*VS) );
    y1 = ( y1*VS+(height*0.5)+(oy*VS) );
    stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
    line(x0,y0,x1,y1);
    }
    
    }
    }
  }
}

You can see the full program at https://editor.p5js.org/hpestock/sketches/Yfagz4Bz3

Joe Dimagio
  • 55
  • 1
  • 1
  • 6
  • If I am to clip the z=p,w=p planes of all lines and exclude anything not in the z+ w+ area of 4-space, were I to plot the z and w as x and y on a 2d graph respectively, should that produce a graph that looks like one quarter of a cube, and would that appear properly in a 4-space projection? – Joe Dimagio Jun 11 '22 at 12:29
  • compare with this [how should i handle (morphing) 4D objects in opengl?](https://stackoverflow.com/a/44970550/2521214) ... try to render 4D teseract after perspective projection for `z,w` it should look like cube inside cube (in the linked answer is example animation of both projection and cross section) – Spektre Aug 23 '22 at 06:52

0 Answers0