/* This is a ray tracing program which works with spheres. */ #include #include // getch #define V_800x600x256 #define V_FILE #include /* +---x |\ | \ y z */ struct VECTOR { float x,y,z; } E = { V_CENX, V_CENY, -550 }; // "E" for eye #define SPHERES 4 struct SPHERE { float x,y,z, // center r; // radius /* for 320x200x256 } S[SPHERES] = { 159, 90, 100, 50, // "S" for sphere 50, 30, 150, 45, 290, 170, 75, 60, 40, 180, 160, 50 }; */ /* for 800x600x256 */ } S[SPHERES] = { 398, 270, 275, 138, // "S" for sphere 125, 90, 413, 124, 725, 510, 206, 165, 100, 540, 440, 138 }; /* 640x480x16 } S[SPHERES] = { 340, 190, 220, 110, // "S" for sphere 100, 72, 330, 99, 580, 408, 165, 132, 80, 432, 352, 110 }; */ void SphereIntersection(VECTOR p1,VECTOR m,int s,float &d,VECTOR &p2,int &s2) { float A,B,C,t,d2,x,y,z; p1.x -= S[s].x; p1.y -= S[s].y; p1.z -= S[s].z; A = 2*(m.x*m.x + m.y*m.y + m.z*m.z); B = 2*(m.x*p1.x + m.y*p1.y + m.z*p1.z); C = B*B - 2*A*(p1.x*p1.x + p1.y*p1.y + p1.z*p1.z - S[s].r*S[s].r); if (C < 0) return; // no intersection t = (-B - sqrt(C))/A; x = m.x*t; y = m.y*t; z = m.z*t; d2 = sqrt(x*x + y*y + z*z); if (t < 0 || (d2 >= d && d >= 0)) return; // intersection farther away than currently found one p1.x += S[s].x; p1.y += S[s].y; p1.z += S[s].z; x += p1.x; y += p1.y; z += p1.z; p2.x = x; p2.y = y; p2.z = z; d = d2; s2 = s; } void ReflectRay(VECTOR &p1,VECTOR &m,int s,VECTOR p2) { float k; VECTOR TP1,CT,B; // T = p2 C = S[s].x,y,z CT.x = p2.x - S[s].x; CT.y = p2.y - S[s].y; CT.z = p2.z - S[s].z; TP1.x = p1.x - p2.x; TP1.y = p1.y - p2.y; TP1.z = p1.z - p2.z; k = (TP1.x*CT.x + TP1.y*CT.y + TP1.z*CT.z)/(CT.x*CT.x + CT.y*CT.y + CT.z*CT.z); B.x = k*CT.x + p2.x; B.y = k*CT.y + p2.y; B.z = k*CT.z + p2.z; m.x = 2*B.x - p1.x - p2.x; m.y = 2*B.y - p1.y - p2.y; m.z = 2*B.z - p1.z - p2.z; p1.x = p2.x; p1.y = p2.y; p1.z = p2.z; } int WhatColour(float x,float y) { VECTOR p1, // point on line p2, m; // direction vector float d; // distance int s,s2,olds; // sphere index p1.x = E.x; p1.y = E.y; p1.z = E.z; m.x = x - E.x; m.y = y - E.y; m.z = 0 - E.z; olds = -1; jump: d = -1; for (s = 0; s < SPHERES; s++) if (s != olds) SphereIntersection(p1,m,s,d,p2,s2); if (d > 0) { ReflectRay(p1,m,s2,p2); olds = s2; goto jump; } /* At this point, "m" and "p" contain a line pointing towards outer space. */ if (m.y == 0) return 101; if (m.y > 0) { // k = 580 p2.x = p1.x - (p1.y-580)*m.x/m.y; p2.z = p1.z - (p1.y-580)*m.z/m.y; s = ((long int)(p2.x/200)) % 2; if (p2.x < 0) s = !(-s); s2 = ((long int)(p2.z/200)) % 2; if (p2.z < 0) s2 = !(-s2); if (s == s2) return 164; else return 101; } else return (-63.0*m.y/sqrt(m.x*m.x+m.y*m.y+m.z*m.z) + 1); /* if (m.y > 0) // pointing down return (63.0*m.y/sqrt(m.x*m.x+m.y*m.y+m.z*m.z) + 101); else return (-63.0*m.y/sqrt(m.x*m.x+m.y*m.y+m.z*m.z) + 1); */ /* if (m.y == 0) return 0; if (m.y > 0) { // k = 580 p2.x = p1.x - (p1.y-580)*m.x/m.y; p2.z = p1.z - (p1.y-580)*m.z/m.y; s = ((long int)(p2.x/200)) % 2; if (p2.x < 0) s = !(-s); s2 = ((long int)(p2.z/200)) % 2; if (p2.z < 0) s2 = !(-s2); if (s == s2) return 15; else return 0; } else { // k = -100 p2.x = p1.x - (p1.y+100)*m.x/m.y; p2.z = p1.z - (p1.y+100)*m.z/m.y; s = ((long int)(p2.x/200)) % 2; if (p2.x < 0) s = !(-s); s2 = ((long int)(p2.z/200)) % 2; if (p2.z < 0) s2 = !(-s2); if (s == s2) return LIGHTBLUE; else return LIGHTCYAN; } */ } void Rect(int x,int y,int c,int x2,int y2) { int a,b; for (a = x; a < x+x2; a++) for (b = y; b < y+y2; b++) PutPixel(a,b,c); } main() { int x,y; GoGraph(); for (x = 1; x <= 64; x++) SetPalette(x,0,64-x,63); // sky for (x = 101; x <= 164; x++) SetPalette(x,0,x-101,0); /* for (x = 0; x <= V_MAXX; x+=20) for (y = 0; y <= V_MAXY; y+=20) // PutPixel(x,y,WhatColour(x,y)); Rect(x,y,WhatColour(x,y),19,19); */ for (x = 0; x <= V_MAXX; x++) for (y = 0; y <= V_MAXY; y++) PutPixel(x,y,WhatColour(x,y)); getch(); getch(); getch(); save_screen("C:\\BCPP2\\GRAPHX.DAT\\RAYS.DAT"); }