class intersectionTest{ private: public: vec3 intersectionPosition; vec3 normalDirection; vec3 viewVec; vec3 texCoords; //only use x and y double intersectionDistance; float refractiveIndex; float reflectiveIndex; bool foundPoint; bool inBounds; ImageColor texture; //material properties vec3 ambientColor; vec3 diffuseColor; vec3 specularColor; double shininess; vec3 emissionColor; double translucency; double reflectivity; double dielectric; //constructor initializes the variables void initializeTest() { intersectionPosition.x = 0; intersectionPosition.y = 0; intersectionPosition.z = 0; normalDirection.x = 0; normalDirection.y = 0; normalDirection.z = 0; texCoords.x = 0; texCoords.y = 0; texCoords.z = 0; intersectionDistance = 100000000; foundPoint = false; inBounds = false; translucency = 0; reflectivity = 0; dielectric = 0; } //ray - triangle intersection test bool rayTriangleIntersection(vec3 position, vec3 viewVec, vertex v1, vertex v2, vertex v3) { //need to define the infinite plane that the triangle lies on. do a cross product of two vectors in the trianle to get the normal vec3 v = vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); vec3 normal = v.crossProduct(vec3(v1.x - v3.x, v1.y - v3.y, v1.z - v3.z)); normal.normalize(); //now find the distance from the position to the point on the plane the ray intersects with vec3 A = vec3(v1.x, v1.y, v1.z); vec3 offset(A.x - position.x, A.y - position.y, A.z - position.z);//(position.x - A.x, position.y - A.y, position.z - A.z); float t = (A.dotProduct(normal) - position.dotProduct(normal))/viewVec.dotProduct(normal); vec3 intersectionPoint = vec3(position.x + viewVec.x*t, position.y + (viewVec.y*t), position.z + viewVec.z*t); //now check whether our intersection point is inside or outside of the triangle float triangleArea = vec3(vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z).crossProduct(vec3(v1.x - v3.x, v1.y - v3.y, v1.z - v3.z))).distance()/2.0f; vec3 cross1 = vec3(intersectionPoint.x - v1.x, intersectionPoint.y - v1.y, intersectionPoint.z - v1.z).crossProduct(vec3(intersectionPoint.x - v2.x, intersectionPoint.y - v2.y, intersectionPoint.z - v2.z)); float area1 = cross1.distance()/2.0f; vec3 cross2 = vec3(intersectionPoint.x - v2.x, intersectionPoint.y - v2.y, intersectionPoint.z - v2.z).crossProduct(vec3(intersectionPoint.x - v3.x, intersectionPoint.y - v3.y, intersectionPoint.z - v3.z)); float area2 = cross2.distance()/2.0f; vec3 cross3 = vec3(intersectionPoint.x - v3.x, intersectionPoint.y - v3.y, intersectionPoint.z - v3.z).crossProduct(vec3(intersectionPoint.x - v1.x, intersectionPoint.y - v1.y, intersectionPoint.z - v1.z)); float area3 = cross3.distance()/2.0f; float sum = area1 + area2 + area3; if(abs(sum - triangleArea) < 0.001 && t < intersectionDistance && t > 0) //I'm sure the numbers won't be perfect, I don't know what a reasonable error threshold would be, play with it later if things don't look right { intersectionDistance = t; intersectionPosition = intersectionPoint; ///////////////////////////////////////////////// //figure out the normals and texture coordinates ///////////////////////////////////////////////// //cross1 relates to v3 //cross2 relates to v1 //cross3 relates to v2 float v1Contribution = area2/sum; float v2Contribution = area3/sum; float v3Contribution = area1/sum; //need to normalize the normals vec3 norm1 = vec3(v1.nx, v1.ny, v1.nz); norm1.normalize(); vec3 norm2 = vec3(v2.nx, v2.ny, v2.nz); norm2.normalize(); vec3 norm3 = vec3(v3.nx, v3.ny, v3.nz); norm3.normalize(); normalDirection.x = norm1.x*v1Contribution + norm2.x*v2Contribution + norm3.x*v3Contribution; normalDirection.y = norm1.y*v1Contribution + norm2.y*v2Contribution + norm3.y*v3Contribution; normalDirection.z = norm1.z*v1Contribution + norm2.z*v2Contribution + norm3.z*v3Contribution; double positionCorrection = 0.001; intersectionPosition.x = intersectionPoint.x + normalDirection.x*positionCorrection; intersectionPosition.y = intersectionPoint.y + normalDirection.y*positionCorrection; intersectionPosition.z = intersectionPoint.z + normalDirection.z*positionCorrection; texCoords.x = v1.u*v1Contribution + v2.u*v2Contribution + v3.u*v3Contribution; texCoords.y = v1.v*v1Contribution + v2.v*v2Contribution + v3.v*v3Contribution; ///////////////////////////////////////////////// foundPoint = true; return true; } else //else we don't have an intersection { return false; } } //just do a quick ray-sphere intersection test and return whether it hits or not bool raySphereIntersection(vec3 position, vec3 viewVec, vec3 sphereOrigin, float radius) { position = vec3(position.x - sphereOrigin.x, position.y - sphereOrigin.y, position.z - sphereOrigin.z); double a = (viewVec.x*viewVec.x + viewVec.y*viewVec.y + viewVec.z*viewVec.z); double b = 2*(position.x*viewVec.x + position.y*viewVec.y + position.z*viewVec.z); double c = position.x*position.x + position.y*position.y + position.z*position.z - radius*radius; //check if the discriminant is negative, if it is then return false, otherwise compute intersectionPosition and the rest double discriminant = (b*b) - (4*a*c); if(discriminant < 0.0) return false; else //find the intersection point { inBounds = true; double t1 = (-b + sqrt(discriminant))/(2*a); double t2 = (-b - sqrt(discriminant))/(2*a); double t;// t = Min(t1, t2); if( t1 < t2) t = t1; else t = t2; if( t < intersectionDistance && t > 0) { foundPoint = true; intersectionDistance = t; intersectionPosition = vec3(position.x + (viewVec.x*t), position.y + (viewVec.y*t), position.z + (viewVec.z*t) ); //set the normal for the intersection point on the sphere normalDirection.x = intersectionPosition.x; normalDirection.y = intersectionPosition.y; normalDirection.z = intersectionPosition.z; normalDirection.normalize(); texCoords.x = normalDirection.x; texCoords.y = normalDirection.z; //set the actual intersection point for the sphere double positionCorrection = 0.0001; intersectionPosition.x += sphereOrigin.x + normalDirection.x*positionCorrection; intersectionPosition.y += sphereOrigin.y + normalDirection.y*positionCorrection; intersectionPosition.z += sphereOrigin.z + normalDirection.z*positionCorrection; return true; } else { return false; } } } };