how to draw sphere in 3d in computer graphics
Based on the link, it looks similar you're more interested in voxel algorithms for spheres, rather than graphics per se; say something like this folio helps with. You don't want a brawl, only the surface merely.
Midpoint circle algorithm can be used to draw 3D voxel spheres: consider the sphere as a stack of slices, and each slice contains a circumvolve.
In practice, y'all use two nested midpoint circles, the outer defining the radius for the inner one. (Although a naive algorithm drawing circles on tiptop of each other will likely leave holes in the voxels, the midpoint circle algorithm exploits symmetries, and if correctly implemented, no such holes should occur.)
You build vi 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 volition at most change each coordinate by 1, and so holes cannot occur.
The problem with this approach is the complexity: each point you calculate may affect up to 48 voxel cells. (At each cap, each signal is calculated inside an octant, and therefore affects 8 cells. There are half-dozen caps, and 6*8=48.)
I advise a unlike approach.
The equation for the surface of a r-radius sphere centered at ten0 , y0 , z0 , is
(ten - x 0)2 + (y - y 0)2 + (z - z 0)2 = r ii
With integer coordinater, the grid points are rarely exactly on the sphere surface, allow a range of values:
RRMIN ≤ (x - 10 0)2 + (y - y 0)2 + (z - z 0)ii ≤ RRMAX
where RRMIN and RRMAX are constants; specifically, minimum and maximum altitude squared to the sphere center.
I recommend using doubled coordinates for general cases. This allows you to select whether the center of the sphere is centered at a coordinate (implying odd bore), or centered betwixt ii adjacent cordinates (implying even diameter).
If y'all have a SIZE
×SIZE
×SIZE
filigree of voxels (lights, edifice blocks, whatever), and then
int sphere_surface(const char x, const char y, const char z, const char size, const int rrmin, const int rrmax) { const int center = size - (size & 1); /* Size rounded downward to fifty-fifty integer */ const int dx = middle - x - ten, dy = centre - y - y, dz = center - z - z; /* Doubled coordinates */ const int rr = dx*dx + dy*dy + dz*dz; /* Altitude squared */ render (rrmin <= rr) && (rr <= rrmax); }
returns 1 if betoken (10
,y
,z
) is within the surface region of the sphere centered in the cube. (Technically, it returns if the distance from that point to the eye of the size
-sized cube is within sqrt(rrmin)/2
and sqrt(rrmax)/ii
, inclusive.)
The "right" values of rrmin
and rrmax
are highly context dependent. rrmax
is typically somewhere near size*size
(recall, the office uses doubled coordinates), with rrmin
somewhat less.
For instance, if you take a 3×3×iii grid, you just want the six center cells on each face to fulfill the status; you can do that with size=3
, rrmin=1
, rrmax=4
:
If you have a 4×iv×four filigree, you want the four centre cells on each face up to fulfill the condition (so a full of 24 of the 64 cells are considered to be on the sphere surface); y'all can do that with size=four
, rrmin=11
, rrmax=eleven
:
With a 5×five×5 grid, we get to the interesting side effects of the above algorithm.
size=5
, rrmin=8
, rrmax=16
yields a very "angular" sphere, well-nigh a cube standing on a corner:
size=5
, rrmin=12
, rrmax=xx
yields my favourite approximate sphere:
size=5
, rrmin=16
, rrmax=24
yields a rounded cube (each face a 3×3 flat):
Obviously, using rrmin=0
includes all inner cells, too, yielding a brawl instead of just the surface of a sphere.
Every bit the grid size increases, the more than variants of each size sphere you can represent.
The above function is especially useful on microcontrollers, considering you tin can merely loop through your lattice, updating the state at each indicate, as y'all wish. Furthermore, most microcontrollers are tight on memory, simply accept very fast (single-clock) addition, subtraction, and multiplication instructions. (Although a 16×xvi-bit multiplication with 32-fleck result typically takes two or more instructions.)
A typical microcontroller does not take the ROM/wink capability to shop enough interesting voxel patterns, and only a few have DMA capability from an SD card via SPI (so you could simply load "frames" of voxel patterns from a microSD menu), simply functions similar the above can produce interesting shapes with few inputs -- and peculiarly inputs y'all tin can interpolate.
The higher up office can likewise be adapted for approximated antialising (past comparing rr
to rrmin
and rrmax
), in case your voxels are not just binary, but due east.chiliad. PWM-controlled LEDs.
Since visualizing the above is typically a bit difficult, here is the quick lilliputian hack that I used to generate the above images. Information technology outputs an SVG image to standard output, and ASCII slices to standard mistake, when given size
, rrmin
, and rrmax
every bit command-line parameters.
#include <stdlib.h> #include <string.h> #include <stdio.h> #define Border 2 #ascertain 90(x,y,z) ((10)*16 + (y)*12) #ascertain YC(ten,y,z) ((x)*6 - (y)*eight - (z)*17) static int xt = 0; static int yt = 0; static void fcube(FILE *out, const int x, const int y, const int z, const int fill) { const int 90 = xt + Xc(10,y,z); const int yc = yt + YC(10,y,z); fprintf(out, "<path d=\"M%d,%dl16,six,12,-8,0,-17,-16,-half dozen,-12,8z\" fill up=\"#%06x\" stroke=\"#000\" />\due north", 90, yc, fill up & 0xFFFFFF); fprintf(out, "<path d=\"M%d,%dl16,6,12,-8m-12,8l0,17\" fill=\"none\" stroke=\"#000\" />\n", xc, yc-17); } static unsigned long rrmin = 0UL; static unsigned long rrmax = 0UL; static int center = 0; static int surface(const int x, const int y, const int z) { /* Doubled coordinates: */ const long dx = two*ten - heart, dy = two*y - heart, dz = 2*z - centre; const unsigned long rr = dx*dx + dy*dy + dz*dz; return (rrmin <= rr) && (rr <= rrmax); } int main(int argc, char *argv[]) { int width, height; int size, x, y, z; char dummy; if (argc != iv || !strcmp(argv[ane], "-h") || !strcmp(argv[1], "--aid")) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %due south SIZE RRMIN RRMAX\n", argv[0]); fprintf(stderr, "Where\n"); fprintf(stderr, " SIZE is the size of the voxel cube\n"); fprintf(stderr, " RRMIN is the minimum distance squared, and\northward"); fprintf(stderr, " RRMAX is the maximum distance squared,\north"); fprintf(stderr, " using doubled coordinates.\northward"); fprintf(stderr, "\northward"); fprintf(stderr, "Examples:\n"); fprintf(stderr, " %s 3 1 4\n", argv[0]); fprintf(stderr, " %s 4 11 11\north", argv[0]); fprintf(stderr, " %s 5 8 16\northward", argv[0]); fprintf(stderr, " %s five 12 20\north", argv[0]); fprintf(stderr, " %due south v 16 24\north", argv[0]); fprintf(stderr, "\northward"); return EXIT_FAILURE; } if (sscanf(argv[one], " %d %c", &size, &dummy) != one || size < 3) { fprintf(stderr, "%south: Invalid size.\northward", argv[1]); return EXIT_FAILURE; } if (sscanf(argv[2], " %lu %c", &rrmin, &dummy) != 1) { fprintf(stderr, "%s: Invalid rrmin.\northward", argv[2]); render EXIT_FAILURE; } if (sscanf(argv[iii], " %lu %c", &rrmax, &dummy) != 1 || rrmax < rrmin) { fprintf(stderr, "%south: Invalid rrmax.\due north", argv[3]); return EXIT_FAILURE; } /* Summate coordinate range. */ { int xmin = Ninety(0,0,0); int ymin = YC(0,0,0); int xmax = Ninety(0,0,0); int ymax = YC(0,0,0); for (z = 0; z <= size; z++) for (y = 0; y <= size; y++) for (x = 0; x <= size; x++) { const int xc = XC(x,y,z); const int yc = YC(x,y,z); if (xc < xmin) xmin = ninety; if (xc > xmax) xmax = xc; if (yc < ymin) ymin = yc; if (yc > ymax) ymax = yc; } xt = BORDER - xmin; width = xmax - xmin + 2*BORDER; yt = Border - ymin; height = ymax - ymin + 2*BORDER; } eye = size - 1; /* SVG preamble. */ printf("<?xml version=\"one.0\"?>\n"); printf("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 %d %d\">\n", width, height); printf("<path d=\"G%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+90(size, 0, 0), yt+YC(size, 0, 0), xt+XC(size,size, 0), yt+YC(size,size, 0), xt+XC(size,size,size), yt+YC(size,size,size), xt+90(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\" make full=\"none\" stroke=\"#666666\"/>\n", xt+XC( 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+90( 0,size, 0), yt+YC( 0,size, 0), xt+Ninety( 0,size,size), yt+YC( 0,size,size)); for (z = 0; z < size; z++) for (y = size - 1; y >= 0; y--) for (10 = 0; ten < size; ten++) if (surface(x,y,z)) fcube(stdout, ten, y, z, 0x00CCFF); printf("</svg>\n"); for (z=0; z < size; z++) { for (y = 0; y < size; y++) { for (x = 0; 10 < size; 10++) fputc(surface(x,y,z) ? 'Ten' : '.', stderr); fputs(" ", stderr); for (ten = 0; 10 < size; x++) fputc(surface(x,z,y) ? 'X' : '.', stderr); fputs(" ", stderr); for (ten = 0; x < size; x++) fputc(surface(y,z,x) ? '10' : '.', stderr); fputc('\due north', stderr); } fputc('\n', stderr); } return EXIT_SUCCESS; }
I didn't bother to finesse the output; you can quite hands due east.g. cull dissimilar colors for each face, maybe add shadows to the background planes, et cetera.
The above images were created with this program, then converted to PNG using GIMP, merely I recommend using your browser to view the generated files locally.
Questions?
Source: https://stackoverflow.com/questions/25057471/drawing-3d-sphere-in-c-c
0 Response to "how to draw sphere in 3d in computer graphics"
Post a Comment