1

I'm having trouble converting 3D coordinates to 2D then print all the points in an isometric projection in C.

I tried this :

u = x / z;
v = y / z;

But when z = 0, my function enters an infinite loop.

I also found some stuff on google but this didn't worked with negative Z (I want bumps when Z > 0 and pits when Z < 0)

Here is how I work. My function gets a file that looks like this

0 0 0 0 0 0 0 0 0 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 0 0 0 0 0 0 0 0 0

the numbers represent the z coordinate and the origin (0;0;0) is upper left.

2 Answers2

3

Sounds like you are mixing concepts. Division by third coordinate only makes sense if you consider the 3D origin to be your camera, and the z=1 plane to be your screen. In that case, points with z=0 get projected to infinity. Usually you have a view frustrum to clip such infinite coordinates. And if your input is expected to have z=0, then that can't work.

And in any case, it's not isometric, since the z axis plays a different role than all the other axes. An isometric projection is a special case of an parallel projection, while your division suggests a central projection unless it's the dehomogenization step after a planar projective transformation.

For isometric projection I suggest you try the following instead:

u = x*cos(α) + y*cos(α+120°) + z*cos(α-120°)
v = x*sin(α) + y*sin(α+120°) + z*sin(α-120°)

although for C you'll have to convert to radians. α will rotate your view, choose however you want to align stuff. If you choose α as a multiple of 30° you'll get fairly nice numbers involving just a simple square root. The sin/cos pairs simply describe three vectors of unit length at 120° from one another. You use these as the images of the 3D unit vectors. You could write this as a matrix times vector multiplication as well, if you prefer.

MvG
  • 57,380
  • 22
  • 148
  • 276
1

Here is a non optimized implementation of the mathematical equations found on the wikipedia page about isometric projection

It boils down to the following function :

int toIsometric2D(double x, double y,double z, double *u, double*v){
    *u=(x-z)/sqrt(2);
    *v=(x+2*y+z)/sqrt(6);
    return 0;
}

To compile the following code : gcc main.c -o main -lm

#include <stdio.h>
#include <math.h>


int toIsometric2D(double x, double y,double z, double *u, double*v){
    *u=(x-z)/sqrt(2);
    *v=(x+2*y+z)/sqrt(6);
    return 0;
}

int main(){
    int n=10;
    double z[n][n];
    int i,j;

    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            z[i][j]=0;
        }
    }

    for(i=2;i<8;i++){
        for(j=2;j<8;j++){
            z[i][j]=9;
        }
    }

    for(i=4;i<6;i++){
        for(j=4;j<6;j++){
            z[i][j]=-5;
        }
    }

    double u[n][n];
    double v[n][n];

    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            toIsometric2D(i, j,z[i][j], &u[i][j],&v[i][j]);
        }
    }

    //print to file -> gnuplot

    FILE* fp;
    fp=fopen("data.dat","w");
    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            fprintf(fp,"%g %g %g\n",u[i][j],v[i][j],z[i][j]);
        }
    }

    fclose(fp);
}

It produces a file data.dat with u v z in it. It can be displayed by the gnuplot software by following the first answer to How to make points one color when a third column equals zero, and another color otherwise, in Gnuplot? The gnuplot command is :

plot[-7:10][-5:15] "data.dat" u 1:2:( $3 ) with points pt 7 ps 3 palette
Community
  • 1
  • 1
francis
  • 9,525
  • 2
  • 25
  • 41