how to draw a 3d c

Based on the link, it looks similar you lot're more interested in voxel algorithms for spheres, rather than graphics per se; say something like this page helps with. You don't want a brawl, simply the surface only.

Midpoint circle algorithm can be used to draw 3D voxel spheres: consider the sphere equally a stack of slices, and each slice contains a circle.

In practise, you utilise two nested midpoint circles, the outer defining the radius for the inner 1. (Although a naive algorithm drawing circles on elevation of each other volition probable leave holes in the voxels, the midpoint circle algorithm exploits symmetries, and if correctly implemented, no such holes should occur.)

Y'all build six caps in tandem, like etching a cube into a sphere. Since the surface slopes on each cap are always less than 1, going outwards on a cap will at most modify each coordinate by 1, so holes cannot occur.

The trouble with this arroyo is the complexity: each indicate you calculate may affect up to 48 voxel cells. (At each cap, each betoken is calculated within an octant, and therefore affects eight cells. At that place are six caps, and 6*8=48.)

I propose a dissimilar arroyo.

The equation for the surface of a r-radius sphere centered at ten0 , y0 , z0 , is

(10 - ten 0)2 + (y - y 0)ii + (z - z 0)2 = r two

With integer coordinater, the grid points are rarely exactly on the sphere surface, permit a range of values:

RRMIN ≤ (x - ten 0)2 + (y - y 0)2 + (z - z 0)2RRMAX

where RRMIN and RRMAX are constants; specifically, minimum and maximum distance squared to the sphere eye.

I recommend using doubled coordinates for full general cases. This allows you lot to select whether the eye of the sphere is centered at a coordinate (implying odd diameter), or centered between two side by side cordinates (implying even diameter).

If yous have a SIZE×SIZE×SIZE filigree of voxels (lights, building blocks, whatsoever), then

          int sphere_surface(const char ten, const char y, const char z,                    const char size, const int rrmin, const int rrmax) {     const int center = size - (size & 1); /* Size rounded downwardly to fifty-fifty integer */     const int dx = center - 10 - 10,               dy = center - y - y,               dz = heart - z - z;        /* Doubled coordinates */     const int rr = dx*dx + dy*dy + dz*dz; /* Altitude squared */     return (rrmin <= rr) && (rr <= rrmax); }                  

returns ane if point (x,y,z) is within the surface region of the sphere centered in the cube. (Technically, it returns if the altitude from that point to the center of the size-sized cube is within sqrt(rrmin)/2 and sqrt(rrmax)/2, inclusive.)

The "correct" values of rrmin and rrmax are highly context dependent. rrmax is typically somewhere near size*size (remember, the function uses doubled coordinates), with rrmin somewhat less.

For example, if you take a 3×three×3 grid, you only desire the six centre cells on each face to fulfill the condition; you tin can do that with size=iii, rrmin=one, rrmax=4:

size=3, rrmin=1, rrmax=4

If you lot have a four×four×four grid, you want the iv centre cells on each face to fulfill the condition (and then a total of 24 of the 64 cells are considered to be on the sphere surface); you can do that with size=4, rrmin=11, rrmax=eleven:

size=4, rrmin=11, rrmax=11

With a 5×v×5 grid, we get to the interesting side effects of the above algorithm.

size=5, rrmin=8, rrmax=16 yields a very "angular" sphere, almost a cube standing on a corner:

size=5, rrmin=8, rrmax=16

size=v, rrmin=12, rrmax=20 yields my favourite approximate sphere:

size=5, rrmin=12, rrmax=20

size=5, rrmin=16, rrmax=24 yields a rounded cube (each face up a 3×three apartment):

size=5, rrmin=16, rrmax=24

Manifestly, using rrmin=0 includes all inner cells, too, yielding a ball instead of just the surface of a sphere.

Every bit the grid size increases, the more than variants of each size sphere y'all can represent.

The above function is especially useful on microcontrollers, considering you lot can but loop through your lattice, updating the state at each point, as you wish. Furthermore, most microcontrollers are tight on retentivity, merely accept very fast (single-clock) addition, subtraction, and multiplication instructions. (Although a 16×16-scrap multiplication with 32-bit upshot typically takes ii or more instructions.)

A typical microcontroller does not accept the ROM/flash capability to store plenty interesting voxel patterns, and only a few have DMA capability from an SD carte du jour via SPI (so yous could just load "frames" of voxel patterns from a microSD carte), but functions like the in a higher place can produce interesting shapes with few inputs -- and particularly inputs y'all can interpolate.

The to a higher place function can also be adapted for approximated antialising (by comparing rr to rrmin and rrmax), in instance your voxels are not simply binary, merely e.k. PWM-controlled LEDs.


Since visualizing the above is typically a flake difficult, here is the quick picayune hack that I used to generate the above images. It outputs an SVG image to standard output, and ASCII slices to standard error, when given size, rrmin, and rrmax as command-line parameters.

          #include <stdlib.h> #include <string.h> #include <stdio.h>  #define   Edge  2 #define   90(10,y,z) ((10)*16 + (y)*12) #define   YC(x,y,z) ((ten)*vi - (y)*viii - (z)*17)  static int xt = 0; static int yt = 0;  static void fcube(FILE *out, const int ten, const int y, const int z, const int make full) {     const int ninety = xt + XC(x,y,z);     const int yc = yt + YC(x,y,z);     fprintf(out, "<path d=\"G%d,%dl16,6,12,-8,0,-17,-sixteen,-six,-12,8z\" fill=\"#%06x\" stroke=\"#000\" />\n", xc, yc, fill & 0xFFFFFF);     fprintf(out, "<path d=\"Chiliad%d,%dl16,6,12,-8m-12,8l0,17\" fill=\"none\" stroke=\"#000\" />\n", 90, yc-17); }  static unsigned long rrmin = 0UL; static unsigned long rrmax = 0UL; static int           center = 0;  static int surface(const int ten, const int y, const int z) {     /* Doubled coordinates: */     const long dx = 2*x - eye,                dy = 2*y - middle,                dz = ii*z - center;     const unsigned long rr = dx*dx + dy*dy + dz*dz;      return (rrmin <= rr) && (rr <= rrmax); }  int principal(int argc, char *argv[]) {     int  width, height;     int  size, x, y, z;     char dummy;      if (argc != 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {         fprintf(stderr, "\n");         fprintf(stderr, "Usage: %southward SIZE RRMIN RRMAX\n", argv[0]);         fprintf(stderr, "Where\n");         fprintf(stderr, "       SIZE    is the size of the voxel cube\north");         fprintf(stderr, "       RRMIN   is the minimum distance squared, and\n");         fprintf(stderr, "       RRMAX   is the maximum altitude squared,\northward");         fprintf(stderr, "               using doubled coordinates.\n");         fprintf(stderr, "\n");         fprintf(stderr, "Examples:\north");         fprintf(stderr, "       %s three 1 4\n", argv[0]);         fprintf(stderr, "       %south iv 11 11\due north", argv[0]);         fprintf(stderr, "       %s five 8 xvi\n", argv[0]);         fprintf(stderr, "       %southward 5 12 20\n", argv[0]);         fprintf(stderr, "       %southward 5 xvi 24\n", argv[0]);         fprintf(stderr, "\due north");         return EXIT_FAILURE;     }      if (sscanf(argv[1], " %d %c", &size, &dummy) != ane || size < 3) {         fprintf(stderr, "%southward: Invalid size.\northward", argv[1]);         render EXIT_FAILURE;     }      if (sscanf(argv[ii], " %lu %c", &rrmin, &dummy) != 1) {         fprintf(stderr, "%s: Invalid rrmin.\n", argv[ii]);         return EXIT_FAILURE;     }      if (sscanf(argv[3], " %lu %c", &rrmax, &dummy) != 1 || rrmax < rrmin) {         fprintf(stderr, "%southward: Invalid rrmax.\n", argv[iii]);         return EXIT_FAILURE;     }      /* Summate coordinate range. */     {   int xmin = Xc(0,0,0);         int ymin = YC(0,0,0);         int xmax = XC(0,0,0);         int ymax = YC(0,0,0);          for (z = 0; z <= size; z++)             for (y = 0; y <= size; y++)                 for (ten = 0; x <= size; 10++) {                     const int 90 = XC(x,y,z);                     const int yc = YC(x,y,z);                     if (xc < xmin) xmin = xc;                     if (xc > xmax) xmax = xc;                     if (yc < ymin) ymin = yc;                     if (yc > ymax) ymax = yc;                 }           xt = Border - xmin;         width = xmax - xmin + two*BORDER;          yt = Border - ymin;         height = ymax - ymin + 2*BORDER;     }      centre = size - ane;      /* SVG preamble. */     printf("<?xml version=\"1.0\"?>\n");     printf("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 %d %d\">\n", width, peak);     printf("<path d=\"Chiliad%d,%dL%d,%d,%d,%d,%d,%d,%d,%d,%d,%dz\" fill=\"#f7f7f7\" stroke=\"#666666\"/>\n",             xt+XC(   0,   0,   0), yt+YC(   0,   0,   0),             xt+XC(size,   0,   0), yt+YC(size,   0,   0),             xt+Ninety(size,size,   0), yt+YC(size,size,   0),             xt+XC(size,size,size), yt+YC(size,size,size),             xt+XC(0,   size,size), yt+YC(   0,size,size),             xt+XC(0,      0,size), yt+YC(   0,   0,size));     printf("<path d=\"M%d,%dL%d,%d,%d,%dM%d,%dL%d,%d\" fill=\"none\" stroke=\"#666666\"/>\n",             xt+90(   0,   0,   0), yt+YC(   0,   0,   0),             xt+XC(   0,size,   0), yt+YC(   0,size,   0),             xt+Xc(size,size,   0), yt+YC(size,size,   0),             xt+Xc(   0,size,   0), yt+YC(   0,size,   0),             xt+90(   0,size,size), yt+YC(   0,size,size));     for (z = 0; z < size; z++)         for (y = size - 1; y >= 0; y--)             for (x = 0; ten < size; 10++)                 if (surface(x,y,z))                     fcube(stdout, x, y, z, 0x00CCFF);     printf("</svg>\due north");      for (z=0; z < size; z++) {         for (y = 0; y < size; y++) {             for (10 = 0; x < size; x++)                 fputc(surface(10,y,z) ? 'X' : '.', stderr);             fputs("   ", stderr);             for (x = 0; x < size; x++)                 fputc(surface(x,z,y) ? '10' : '.', stderr);             fputs("   ", stderr);             for (x = 0; x < size; 10++)                 fputc(surface(y,z,10) ? 'X' : '.', stderr);             fputc('\north', stderr);         }         fputc('\n', stderr);     }      return EXIT_SUCCESS; }                  

I didn't bother to finesse the output; you can quite easily e.thousand. cull different colors for each face, possibly add together shadows to the background planes, et cetera.

The to a higher place images were created with this program, then converted to PNG using GIMP, but I recommend using your browser to view the generated files locally.

Questions?

colemanawasine1947.blogspot.com

Source: https://stackoverflow.com/questions/25057471/drawing-3d-sphere-in-c-c

0 Response to "how to draw a 3d c"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel