• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

sheepsteak

Members
  • Content count

    16
  • Joined

  • Last visited

Community Reputation

122 Neutral

About sheepsteak

  • Rank
    Member
  1. I need an engine that allows me to create multiple scenes and multiple views of the scenes. I'm working on an engineering application that will be loading in 3D scenes from files and displaying them. I've had a go at writing something myself in Managed DirectX but most of my time has gone into prototyping and creating the different structural components from sizes in the file. I was wondering since there are quite a few C# 3D engines out there now if any suited my needs? I've had a look at Axiom but it doesn't seem to handle multiple scenes. I also found one that sounded great,
  2. You can still use XNA as you would Managed DirectX. Just add the references then you still have access to the GraphicsDevice and can use it exactly the same way as you did MDX. It sounds like you are using swap chains in MDX and these are not in XNA. However, you can get round this by creating a back buffer bigger than all the controls you will be drawing to then using that to present to each control. Or as someone else said, SlimDX is another option. I haven't tried that yet though.
  3. That link seems to point back to this thread. [wink] Well I think I'm almost there. But there are still a few problems. If I define the start node as on the origin and put the end node at (50, 5, 0) then the tube should point along the x-axis with a slight elevation. However, it looks like this... As you can see there is a slight rotation around the x-axis. I'll post the code where I rotate the points. // Rotate all vertices so that they point in direction of EndNode. // EndNode vertices are on top of the StartNode ones at the moment. Vector3 startToEnd; startToEnd = Vector3.Subtract(EndNode.Position, StartNode.Position); startToEnd.Normalize(); // Use dot product to obtain angle float angle; Vector3 currentTarget = new Vector3(0, 0, 1); angle = Vector3.Dot(currentTarget, startToEnd); angle = (float)Math.Acos(angle); // Use cross product to get the axis of rotation and create a matrix Vector3 rotationAxis; rotationAxis = Vector3.Cross(currentTarget, startToEnd); Matrix rotationMatrix = Matrix.RotationAxis(rotationAxis, angle); // Apply matrix to all vertices Vector3 pos; for (int i = 0; i < 16; i++) { pos = _vertices[i].Position; pos.TransformCoordinate(rotationMatrix); _vertices[i].Position = pos; } // Extrude along the vector from start node to end node Vector3 temp; Vector3 endToStart = EndNode.Position - StartNode.Position; for (int i = 8; i < 16; i++) { temp = _vertices[i].Position + endToStart; _vertices[i].Position = temp; } Any idea where things are going wrong?
  4. I'm creating a hollow 3D rectangular tube shape manually. I have a start node and an end node (points in world space) where the shape obviously begins and ends. I'm also given the width and height of the tube and the thickness of the wall. At the moment I'm creating 16 vertices and the required indices to create the shape. But I need the 8 vertices at each end to face each other along the vector that runs from the start to end nodes. Given that the end node could be in any direction from the start node I need to rotate the vertices on some axis to make them face each other. I guess I have the option of creating the vertices at each end in the x-z plane and then constructing a matrix to rotate them to the required position. Or, I could somehow work out as I'm creating each vertex where it should be in relation to the centre start node. I'm thinking the first option is best but my maths is a bit rusty. I know I need to find an arbitrary axis to rotate on and the angle but I'm a bit stumped after that. I'll eventually be reading in nodes from a file and the necessary measurements but I'm trying to get this sorted first. I've attached a screen of the shape I have so far. Bear in mind that in the screen the ends are facing each other by default.
  5. I thought it sounded too good to be true. [embarrass]
  6. I've battled with this problem before and thought you might like to know about FreeGLUT. The original GLUT is quite old now and hasn't been updated since 1998. FreeGLUT also has options for leaving the main loop as stated here in the API documentation. Its virtually identical syntax to GLUT I'm led to believe but I've never tried it myself.
  7. I've used a camera tutorial that I found on Flipcode. I'm having trouble with the rotations but the translations seem fine. I'm using GLUT and my mouse callback looks like this: void Mouse(int pX, int pY) { static int lastX, lastY; if(pX > lastX) gCamera.RotateLocal(-1.0, 0.0, 1.0, 0.0); else if(pX < lastX) gCamera.RotateLocal(1.0, 0.0, 1.0, 0.0); if(pY > lastY) gCamera.RotateLocal(-1.0, 1.0, 0.0, 0.0); else if(pY < lastY) gCamera.RotateLocal(1.0, 1.0, 0.0, 0.0); lastX = pX; lastY = pY; } If you try the compiled exe from here and hold down a mouse button and rotate the pointer in circles you will see how it goes wrong. The teapot starts to rotate around the Z axis. If you do circles in the other direction then it goes back. Use W, A, S and D for FPS-like movement. Any ideas how I can stop this from happening?
  8. Ok thanks I've changed that but I'm still having problems. Here is a shot of whats happening after 2 rays (initial plus 1 reflection): It seems as though whenever I use the TestIntersection or IsLightVisible functions (IsLightVisible is a slightly cut down version and doesn't calculate distance) at the point of intersection with a sphere it messes up. I can't see what is making it do this. Looks as though its passing straight through the spheres though as the right-hand sphere has reflections where it shouldn't. :( #include <GL/glut.h> #include <stdio.h> #include <math.h> //View plane window size #define XMAX 12.0 #define XMIN -12.0 #define YMAX 9.0 #define YMIN -9.0 #define WIDTH 512 #define HEIGHT 384 #define NUMSPHERES 3 //Maximum number of trace depths #define MAX 1 // Data Structures //3D points data structure typedef struct { float x; float y; float z; }Point3D, Vector3D; //Colour data structure typedef struct { float r; float g; float b; }Colour3f; //Sphere data structure typedef struct { float x, y, z;//location float r, g, b;//colour float radius; float KDr, KDg, KDb;//Diffuse reflect float KAr, KAg, KAb;//Ambient reflect float KS; //Specular }Sphere; //Light data structure typedef struct { float x, y, z;//location float r, g, b;//light colour }Light; float dx = (XMAX - XMIN) / WIDTH; float dy = (YMAX - YMIN) / HEIGHT; Sphere sphere[3]; //Centre of camera projection co-ordinates Point3D COP = {0, 0, -10 }; //Pixel array for our viewing plane Colour3f pixels[WIDTH][HEIGHT]; //The light Light light; //Ambient light intensity Colour3f ambient = { 0.7, 0.7, 0.7 }; // Functions prototypes //Display function void display(void); //Idle function void idle(void); // Setup scene function void InitScene(void); //Ray tracing function that generates first ray and calls recursive RayTrace function void RayTraceScene(void); //Recursive raytrace function Colour3f RayTrace(Point3D p, Vector3D ray, int depth); //Tests to see if ray intersects any objects int TestIntersection(Point3D origin, Vector3D ray, Point3D* pi); //Calculates whether the intersection point can see the light bool IsLightVisible(Point3D origin, Vector3D ray); //Finds the normal at intersection point with the sphere Vector3D FindNormal(Point3D& pi, int sphereIndex); //Calculates the reflection ray Vector3D CalcReflect(Vector3D& in, Vector3D& normal); //Normalises a vector void Normalise(Vector3D* vec); //Finds the Dot Product between two vectors float Dot(Vector3D vec1, Vector3D vec2); int main(int argc, char **argv) { //Creating graphics window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGB); glutInitWindowSize(WIDTH, HEIGHT); glutInitWindowPosition(0, 0); glutCreateWindow("Ray Trace"); InitScene(); glutDisplayFunc(display); glutIdleFunc(idle); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, WIDTH, HEIGHT, 0.0, -100.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glutMainLoop(); return 0; } void display() { int i, j; // clear the offscreenbuffer glClearColor(0.0, 0.0, 0.0, 1.0);/*Background colour*/ glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); //Calling raycast function RayTraceScene(); //Displaying scene pixels and forming an image glBegin(GL_POINTS); for (i = 0; i< WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { glColor3f(pixels[i][j].r, pixels[i][j].g, pixels[i][j].b); glVertex2f(i, j); } } glEnd(); glutSwapBuffers(); return; } void idle(void) { glutPostRedisplay(); } void InitScene(void) { sphere[0].x = 0.0; sphere[0].y = 0.0; sphere[0].z = 7.0; sphere[0].radius = 4.0; sphere[0].r = 1.0; sphere[0].g = 0.0; sphere[0].b = 0.0; sphere[0].KAr = 0.2; sphere[0].KAg = 0.1; sphere[0].KAb = 0.1; sphere[0].KDr = 0.9; sphere[0].KDg = 0.1; sphere[0].KDb = 0.1; sphere[0].KS = 0.2; sphere[1].x = 7.0; sphere[1].y = 3.0; sphere[1].z = 5.0; sphere[1].radius = 3.0; sphere[1].r = 0.0; sphere[1].g = 1.0; sphere[1].b = 0.0; sphere[1].KAr = 0.1; sphere[1].KAg = 0.2; sphere[1].KAb = 0.1; sphere[1].KDr = 0.1; sphere[1].KDg = 0.8; sphere[1].KDb = 0.1; sphere[1].KS = 0.3; sphere[2].x = -7.0; sphere[2].y = -3.0; sphere[2].z = 5.0; sphere[2].radius = 3.0; sphere[2].r = 0.0; sphere[2].g = 0.0; sphere[2].b = 1.0; sphere[2].KAr = 0.2; sphere[2].KAg = 0.2; sphere[2].KAb = 0.2; sphere[2].KDr = 0.8; sphere[2].KDg = 0.8; sphere[2].KDb = 1.0; sphere[2].KS = 0.5; light.x = 0.0; light.y = 0.0; light.z = 1.5; light.r = 1.0; light.g = 1.0; light.b = 1.0; } void RayTraceScene(void) { Vector3D ray; float Xp, Yp, Zp = 0.0; int i, j; for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { Xp = XMIN + 0.5 * dx + i * dx; Yp = YMAX - 0.5 * dy - j * dy; Zp = 0; // since image plane is at Z = 0 ray.x = Xp - COP.x; ray.y = Yp - COP.y; ray.z = Zp - COP.z; Normalise(&ray); pixels[i][j] = RayTrace(COP, ray, 0); } } } Colour3f RayTrace(Point3D p, Vector3D ray, int depth) { Point3D pd; Colour3f result = {0.0, 0.0, 0.0}; if(depth > MAX) //If reached maximum trace depth return result; // (0,0,0) else { int sphereHit = TestIntersection(p, ray, &pd); //printf("spherehit = %d\n", sphereHit); if(sphereHit == -1) //If no intersection return result; // BACKGROUND else { Colour3f Idirect = { 0.0, 0.0, 0.0 }; Colour3f Iindirect = { 0.0, 0.0, 0.0 }; Colour3f Itotal = { 0.0, 0.0, 0.0 }; Vector3D lightDirection; Vector3D normal = FindNormal(pd, sphereHit); lightDirection.x = light.x - pd.x; lightDirection.y = light.y - pd.y; lightDirection.z = light.z - pd.z; Normalise(&lightDirection); Vector3D temp; if(TestIntersection(pd, lightDirection, &temp) != -1) //float dot = Dot(normal, lightDirection); //if (dot > 0) { //Idirect.r = 1.0; //Idirect.b = 1.0; //Idirect.g = 1.0; //printf("LIGHT VISIBLE!\n"); Vector3D reflection = CalcReflect(lightDirection, normal); Idirect.r = sphere[sphereHit].KAr * ambient.r + light.r * (sphere[sphereHit].KDr * Dot(normal, lightDirection)) + (sphere[sphereHit].KS * Dot(normal, reflection)); Idirect.g = sphere[sphereHit].KAg * ambient.g + light.g * (sphere[sphereHit].KDg * Dot(normal, lightDirection)) + (sphere[sphereHit].KS * Dot(normal, reflection)); Idirect.b = sphere[sphereHit].KAb * ambient.b + light.b * (sphere[sphereHit].KDb * Dot(normal, lightDirection)) + (sphere[sphereHit].KS * Dot(normal, reflection)); } else { //printf("LIGHT NOT VISIBLE!\n"); Idirect.r = sphere[sphereHit].KAr * ambient.r; Idirect.g = sphere[sphereHit].KAg * ambient.g; Idirect.b = sphere[sphereHit].KAb * ambient.b; } //calculate reflection direction at point pd Vector3D reflect = CalcReflect(ray, normal); Iindirect = RayTrace(pd, reflect, depth + 1); Itotal.r = Idirect.r + Iindirect.r; Itotal.g = Idirect.g + Iindirect.g; Itotal.b = Idirect.b + Iindirect.b; return Itotal; } } } int TestIntersection(Point3D origin, Vector3D ray, Point3D* pi) { int sphereHit = -1; float depth = 10000000; float distance; float A, B, C; int k; for(k = 0; k < NUMSPHERES; k++) { A = powf(ray.x, 2.0) + powf(ray.y, 2.0) + powf(ray.z, 2.0);// = 1 since ray is normalised B = 2 * (ray.x * (origin.x - sphere[k].x) + ray.y * (origin.y - sphere[k].y) + ray.z * (origin.z - sphere[k].z)); //-39.85 C = powf((origin.x - sphere[k].x), 2.0) + powf((origin.y - sphere[k].y), 2.0) + powf((origin.z - sphere[k].z), 2.0) - powf(sphere[k].radius, 2.0); // 375 if(B * B - 4 * C >= 0) { float t0 = (- B - sqrtf(B * B - 4 * C)) / 2; //float t1 = (B + sqrtf(B * B - 4 * C)) / 2; //Find intersect point pi->x = origin.x + ray.x * t0; pi->y = origin.y + ray.y * t0; pi->z = origin.z + ray.z * t0; //Work out distance from origin to intersect point distance = sqrtf((origin.x - pi->x) * (origin.x - pi->x) + (origin.y - pi->y) * (origin.y - pi->y) + (origin.z - pi->z) * (origin.z - pi->z)); if(t0 < depth) { depth = t0; sphereHit = k; } } } return sphereHit; } bool IsLightVisible(Point3D origin, Vector3D ray) { //A, B, and C of the quadratic equation float A, B, C; int k; //Intersection tests carried out according to the number of objects for (k = 0; k < NUMSPHERES; k++) { //A, B, and C of the quadratic equation A = powf(ray.x, 2.0) + powf(ray.y, 2.0) + powf(ray.z, 2.0);// = 1 since ray is normalised B = 2 * (ray.x * (origin.x - sphere[k].x) + ray.y * (origin.y - sphere[k].y) + ray.z * (origin.z - sphere[k].z)); C = powf((origin.x - sphere[k].x), 2.0) + powf((origin.y - sphere[k].y), 2.0) + powf((origin.z - sphere[k].z), 2.0) - powf(sphere[k].radius, 2.0); //Ray tangent to sphere and intersecting in two places to form image of //spheres on viewing plane printf("B: %.2f\n", B); if(B * B - 4 * C >= 0) { //printf("LIGHT CANNOT BE SEEN\n"); return false; } } printf("LIGHT SEEN\n"); return true; } Vector3D FindNormal(Point3D& pi, int sphereIndex) { Vector3D normal; normal.x = (pi.x - sphere[sphereIndex].x) / sphere[sphereIndex].radius; normal.y = (pi.y - sphere[sphereIndex].y) / sphere[sphereIndex].radius; normal.z = (pi.z - sphere[sphereIndex].z) / sphere[sphereIndex].radius; return normal; } Vector3D CalcReflect(Vector3D& in, Vector3D& normal) { // Formula: R = V – 2 * (V·N) * N Vector3D ref; //Vector3D lightTemp = { -light.x, -light.y, -light.z }; ref.x = in.x - (2.0 * Dot(in, normal) * normal.x); ref.y = in.y - (2.0 * Dot(in, normal) * normal.y); ref.z = in.z - (2.0 * Dot(in, normal) * normal.z); /*ref.x = 2 * normal.x * Dot(normal, lightTemp) - lightTemp.x; ref.y = 2 * normal.y * Dot(normal, lightTemp) - lightTemp.y; ref.z = 2 * normal.z * Dot(normal, lightTemp) - lightTemp.z;*/ return ref; } void Normalise(Vector3D* vec) { float length = powf(vec->x, 2.0) + powf(vec->y, 2.0) + powf(vec->z, 2.0); length = sqrtf(length); vec->x /= length; vec->y /= length; vec->z /= length; } float Dot(Vector3D vec1, Vector3D vec2) { return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z; } Any help appreciated.
  9. I'm currently trying to do local illumination in my ray tracer before I go on to do global illumination. All I'm getting are flat colours with my code below. Here is the output I'm getting. After putting in some printfs I can see that my IsLightVisible() function which tests to see if the view to the light is clear from the intersection point seems to think the light is always visible. I'm going to post the whole source since its all related. I'm using GLUT. Bear in mind that there are some things in the RayTrace() function that are not going to be used until I do global illumination (Iindirect etc.). Can anyone who is more experienced with Ray Tracing help? #include <GL/glut.h> #include <stdio.h> #include <math.h> //View plane window size #define XMAX 1.0 #define XMIN -1.0 #define YMAX 1.0 #define YMIN -1.0 #define WIDTH 600 #define HEIGHT 600 //Number of spheres #define NUMSPHERE 3 //Maximum number of relections #define MAX 5 #define BOOL int // Data Structures //3D points data structure typedef struct { float x; float y; float z; }Point3D, Vector3D; //Colour data structure typedef struct { float r; float g; float b; }Colour3f; //Sphere data structure typedef struct { float x, y, z;//location float r, g, b;//colour float radius; float KDr, KDg, KDb;//Diffuse reflect float KAr, KAg, KAb;//Ambient reflect float KS; //Specular }Sphere; //Light data structure typedef struct { float x, y, z;//location float r, g, b;//light colour }Light; //Global variables //array to hold three sphere objects Sphere sphere [3]; //The light Light light; //Centre of camera projection co-ordinates Point3D COP = {0, 0, 3 }; //Pixel array for our viewing plane Colour3f pixels[WIDTH][HEIGHT]; //Ambient light intensity Colour3f ambient = { 0.2, 0.2, 0.2 }; // Functions prototypes //Display function void display(void); //Keyboard function void keyboard(unsigned char key, int x, int y); //Idle function void idle(void); // Setup scene function void InitScene(void); //Main control function for the Ray Tracing void RayTracingScene(void); //Render scene function void RenderScene(void); //Raycasting function Colour3f RayTrace(Point3D p, Vector3D direction, int depth); //Normalises a vector void Normalise(Vector3D* vec); //Finds the Dot Product between two vectors float Dot(Vector3D vec1, Vector3D vec2); //Tests all objects for intersections with the Ray int TestIntersection(Point3D p, Vector3D direction, Point3D* pd); //Sees if the light is visible from the object bool IsLightVisible(Point3D p, Vector3D direction); //Finds the normal for the sphere at the intersection point Vector3D FindNormal(Point3D& pi, int sphereIndex); //Returns the reflection ray of the light on the sphere Vector3D CalcReflect(Vector3D& light, Vector3D& normal); int main(int argc, char **argv) { //Creating graphics window glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGB); glutInitWindowSize(WIDTH, HEIGHT); glutInitWindowPosition(0, 0); glutCreateWindow("Ray Trace"); InitScene(); glutDisplayFunc(display); glutIdleFunc(idle); glutKeyboardFunc(keyboard); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, WIDTH, HEIGHT, 0.0, -100.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glutMainLoop(); return 0; } void InitScene() { //Sphere information: Co-ordinates, radius and colour //Sphere 1 co-ordinates, radius and colour sphere[0].x = 0.0; sphere[0].y = 0.0; sphere[0].z = -2.0; //sphere[0].r = 1.0; //sphere[0].g = 0.0; //sphere[0].b = 0.0; sphere[0].radius = 1.0; sphere[0].KAr = 0.2; sphere[0].KAg = 0.1; sphere[0].KAb = 0.1; sphere[0].KDr = 1.0; sphere[0].KDg = 0.1; sphere[0].KDb = 0.1; sphere[0].KS = 0.7; //Sphere 2 co-ordinates, radius and colour………………………………… sphere[1].x = -1.0; sphere[1].y = 1.0; sphere[1].z = -3.0; /*sphere[1].r = 0.0; sphere[1].g = 1.0; sphere[1].b = 0.0;*/ sphere[1].radius = 1.0; sphere[1].KAr = 0.1; sphere[1].KAg = 0.2; sphere[1].KAb = 0.1; sphere[1].KDr = 0.1; sphere[1].KDg = 0.1; sphere[1].KDb = 0.1; sphere[1].KS = 0.3; //Sphere 3 co-ordinates, radius and colour……………………………… sphere[2].x = 1.0; sphere[2].y = 0.0; sphere[2].z = -4.0; /*sphere[2].r = 0.0; sphere[2].g = 0.0; sphere[2].b = 1.0;*/ sphere[2].radius = 1.0; sphere[2].KAr = 0.1; sphere[2].KAg = 0.1; sphere[2].KAb = 0.2; sphere[2].KDr = 0.1; sphere[2].KDg = 0.1; sphere[2].KDb = 1.0; sphere[2].KS = 0.5; //Light light.x = 0.0; light.y = 5.0; light.z = -2.5; light.r = 0.2; light.g = 0.2; light.b = 0.2; return; } void display() { // clear the offscreenbuffer glClearColor(0.0, 0.0, 0.0, 1.0);/*Background colour*/ glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); //Calling raycast function RenderScene(); glutSwapBuffers(); return; } void keyboard(unsigned char key, int x, int y) { } void idle(void) { glutPostRedisplay(); } void RayTracingScene(void) { int i, j, k = 0; //width and height of each scene pixel float pixelwidth, pixelheight; //dx, dy, and dz are the values of the directional vector of the ray Vector3D v; //Centre of pixels Point3D centreofpix; //Determining the width and height of each pixel pixelwidth = (XMAX - XMIN) / WIDTH; pixelheight = (YMAX - YMIN) / HEIGHT; //Incrementing through our scene for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { //To compare point of first intersection with this large value //Determining the centre of our pixels centreofpix.x = XMIN + pixelwidth * (i + 0.5); centreofpix.y = YMIN + pixelheight * (j + 0.5); centreofpix.z = 0; //dx, dy, and dz are the values of the directional vector of the ray v.x = centreofpix.x-COP.x; v.y = centreofpix.y-COP.y; v.z = centreofpix.z-COP.z; pixels[i][j] = RayTrace(COP, v, 0); //printf("i: %d\tj: %d\tRED: %.2f\tGREEN: %.2f\tBLUE: %.2f\n", i, j, pixels[i][j].r, pixels[i][j].g, pixels[i][j].b); } } } void RenderScene() { RayTracingScene(); int i, j; //Displaying scene pixels and forming an image glBegin(GL_POINTS); for (i = 0; i< WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { glColor3f(pixels[i][j].r, pixels[i][j].g, pixels[i][j].b); glVertex2f(i, j); } } glEnd(); return; } Colour3f RayTrace(Point3D p, Vector3D direction, int depth) { Point3D pd; Colour3f result = {0.0, 0.0, 0.0}; if(depth > MAX) //If reached maximum trace depth return result; // (0,0,0) else { int sphereHit = TestIntersection(p, direction, &pd); //printf("spherehit = %d\n", sphereHit); if(sphereHit == -1) //If no intersection return result; // BACKGROUND else { Colour3f Idirect = { 0.0, 0.0, 0.0 }; Colour3f Iindirect = { 0.0, 0.0, 0.0 }; Colour3f Itotal = { 0.0, 0.0, 0.0 }; Vector3D lightDirection; Vector3D normal = FindNormal(pd, sphereHit); Normalise(&normal); lightDirection.x = light.x - pd.x; lightDirection.y = light.y - pd.y; lightDirection.z = light.z - pd.z; Normalise(&lightDirection); if(IsLightVisible(pd, lightDirection)) { //printf("LIGHT VISIBLE!\n"); Vector3D reflection = CalcReflect(lightDirection, normal); Idirect.r = sphere[sphereHit].KAr * ambient.r + (sphere[sphereHit].KDr * Dot(normal, lightDirection) + sphere[sphereHit].KS * Dot(normal, reflection)); Idirect.g = sphere[sphereHit].KAg * ambient.g + (sphere[sphereHit].KDg * Dot(normal, lightDirection) + sphere[sphereHit].KS * Dot(normal, reflection)); Idirect.b = sphere[sphereHit].KAb * ambient.b + (sphere[sphereHit].KDb * Dot(normal, lightDirection) + sphere[sphereHit].KS * Dot(normal, reflection)); } else { //printf("LIGHT NOT VISIBLE!\n"); Idirect.r = sphere[sphereHit].KAr * ambient.r; Idirect.g = sphere[sphereHit].KAg * ambient.g; Idirect.b = sphere[sphereHit].KAb * ambient.b; } //calculate reflection direction R at point pd ; //Iindirect = RayTrace(pd, r, depth + 1); Itotal.r = Idirect.r;// + Iindirect.r; Itotal.g = Idirect.g;// + Iindirect.g; Itotal.b = Idirect.b;// + Iindirect.b; return Itotal; } } } //end RayTrace() int TestIntersection(Point3D p, Vector3D direction, Point3D* pd) { //Used for the co-ordinates of the intersection point with each sphere Point3D intersectpoint[NUMSPHERE]; //A, B, and C of the quadratic equation float A, B, C; //t-value float t; int k; int sphereNearest = -1; float distance; double depth = 10000000; //Intersection tests carried out according to the number of objects for (k = 0; k < NUMSPHERE; k++) { //A, B, and C of the quadratic equation A = direction.x * direction.x + direction.y * direction.y + direction.z * direction.z; B = (p.x-sphere[k].x) * direction.x + (p.y-sphere[k].y) * direction.y + (p.z-sphere[k].z) * direction.z; C = p.x* p.x+ p.y* p.y+ p.z* p.z-2 * (p.x* sphere[k].x+ p.y * sphere[k].y+ p.z* sphere[k].z) + sphere[k].x* sphere[k].x+ sphere[k].y * sphere[k].y+ sphere[k].z* sphere[k].z-sphere[k].radius* sphere[k].radius; //Ray tangent to sphere and intersecting in two places to form image of //spheres on viewing plane if (B * B - A * C >= 0) { //Determining the point of intersection t = -B - sqrt(B * B - A * C) / A; //Determining the co-ordinates of the intersection point intersectpoint[k].x = p.x + t * direction.x; intersectpoint[k].y = p.y + t * direction.y; intersectpoint[k].z = p.z + t * direction.z; //Using pythagoras to work out distance between intersection point //and COP distance = sqrt((p.x-intersectpoint[k].x) * (p.x-intersectpoint[k].x) + (p.y-intersectpoint[k].y) * (p.y-intersectpoint[k].y) + (p.z-intersectpoint[k]. z ) * ( p.z-intersectpoint[k].z)); //Comparing distance with depth enabling pixels nearest to COP to //form nearest image of sphere if (distance < depth) { sphereNearest = k; depth = distance; } } } if(sphereNearest != -1) *pd = intersectpoint[sphereNearest]; return sphereNearest; } bool IsLightVisible(Point3D p, Vector3D direction) { //A, B, and C of the quadratic equation float A, B, C; int k; //Intersection tests carried out according to the number of objects for (k = 0; k < NUMSPHERE; k++) { //A, B, and C of the quadratic equation A = direction.x * direction.x + direction.y * direction.y + direction.z * direction.z; B = (p.x-sphere[k].x) * direction.x + (p.y-sphere[k].y) * direction.y + (p.z-sphere[k].z) * direction.z; C = p.x* p.x+ p.y* p.y+ p.z* p.z-2 * (p.x* sphere[k].x+ p.y * sphere[k].y+ p.z* sphere[k].z) + sphere[k].x* sphere[k].x+ sphere[k].y * sphere[k].y+ sphere[k].z* sphere[k].z-sphere[k].radius* sphere[k].radius; //Ray tangent to sphere and intersecting in two places to form image of //spheres on viewing plane if (B * B - A * C >= 0) { printf("LIGHT CANNOT BE SEEN\n"); return false; } } return true; } void Normalise(Vector3D* vec) { float length = powf(vec->x, 2.0) + powf(vec->y, 2.0) + powf(vec->z, 2.0); length = sqrt(length); vec->x /= length; vec->y /= length; vec->z /= length; } float Dot(Vector3D vec1, Vector3D vec2) { return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z; } Vector3D FindNormal(Point3D& pi, int sphereIndex) { Vector3D normal; normal.x = pi.x - sphere[sphereIndex].x * (1.0 / sphere[sphereIndex].radius); normal.y = pi.y - sphere[sphereIndex].y * (1.0 / sphere[sphereIndex].radius); normal.z = pi.z - sphere[sphereIndex].z * (1.0 / sphere[sphereIndex].radius); return normal; } Vector3D CalcReflect(Vector3D& light, Vector3D& normal) { Vector3D ref; ref.x = light.x - (2.0 * Dot(light, normal) * normal.x); ref.y = light.y - (2.0 * Dot(light, normal) * normal.y); ref.z = light.z - (2.0 * Dot(light, normal) * normal.z); return ref; }