/*Sends a ray through all of the lenses, and gives the ray emerging from the other side. Warning: this assumes the lenses do not overlap each other, like an actual camera lens system. It also assumes the lenses are sorted.*/ Vector3D traceLenses(Vector3D ray, int iterationLevel){ Vector3D endVector = ray; Point3D rayLensIntersection; int i; for(i = 0; i < globals.numberOfLenses; i++){ rayLensIntersection = lensIntersection(globals.lenses[i], endVector); if(isNullPoint(rayLensIntersection) == false){ if(globals.lenses[i].isConvex == true){ endVector = getRefraction(endVector, lensNormal(globals.lenses[i], rayLensIntersection), 1.0, globals.lenses[i].refractionIndex, rayLensIntersection); } else{ endVector = getRefraction(endVector, lensNormal(globals.lenses[i], rayLensIntersection), globals.lenses[i].refractionIndex, 1.0, rayLensIntersection); } /*printf("Lens %d traced: ", i); printVector(endVector);*/ } else{ /*This shouldn't happen, but if it does, the ray is unaffected by the lens*/ //printf("Lens %d passed\n", i); } } return(endVector); }
Vector refract(Vector vec, Vector normal, ItemPtr item, real refractiveIndexA) { real refractiveIndexB = getRefraction(item, ZERO); //http://en.wikipedia.org/wiki/Refractive_index //http://en.wikipedia.org/wiki/Refraction real refractiveRatio = refractiveIndexA / refractiveIndexB; real cosThetaA = -dot(normal, vec); real sinThetaA2 = 1 - cosThetaA * cosThetaA; real cosThetaB2 = 1 - refractiveRatio * refractiveRatio * sinThetaA2; if(cosThetaB2 < 0) { //no refraction return ZERO; } real cosThetaB = sqrt(cosThetaB2); return vec * refractiveRatio + normal * (refractiveRatio * cosThetaA - cosThetaB); }
int Sphere::refractionDirection(Ray &refraction_ray, Point &hitPoint, Vector &normal, double &t) { /* Water 1.33 Glass 1.50 Quartz crystal 1.54 Glycerin 1.47 Diamond 2.42 */ Ray aux; aux.direction = -refraction_ray.direction; aux.normalizar(); double cosTetaI = aux.direction*normal; /* Producto interno */ double n = 1.0/getRefraction(); /* sin2 + cos2 = 1 */ double cosTetaR = sqrtf(1-pow((n* sqrtf(1-pow(cosTetaI,2)) ),2)); if(cosTetaR ==0.0f) return 0; Vector refractado = refraction_ray.direction*(n) - normal*(n*cosTetaI - cosTetaR ); refraction_ray.direction = refractado; refraction_ray.start = hitPoint; refraction_ray.normalizar(); return 1; /* if( intersection(aux,t) ) { Point hitPoint2; hitPoint2 = aux.start + aux.direction*t; /* direcção é a mesma de antes */ /*refraction_ray.start = hitPoint2; return 1; } else { return 0; }*/ }
Vector getPixel(Ray ray, Stack * stack, real magnitude, real refractiveIndex, int depth, ulong *seed) { ItemPtr item = getClosestItem(ray); if(item==NULL) { return ZERO; } Vector point = getIntersectPoint(item, ray) + ray.from; int specularRoughness = getSpecularRoughness(item, point); Vector normal = getNormal(item, ray, point); Vector diffuseColor = ZERO; Vector specularColor = ZERO; Ray reflection; reflection.ray = reflect(ray.ray, normal); reflection.from = point+(reflection.ray*.001f); if(length2(getDiffuse(item, point))>0 || length2(getSpecular(item, point))>0) { for(int i=0;i<lightNumber;i++) { ItemPtr light = &lights[i]; Vector lightVector = light->center-point; Vector lightPixel = fast_normalize(lightVector); real diffuseFactor = dot(normal, lightPixel); real specularFactor = dot(reflection.ray, lightPixel); if(diffuseFactor>0 || specularFactor>0) { int hitLight=0; Ray movedLightRay; movedLightRay.from=reflection.from; Vector right = getRight(lightPixel); Vector up = getUp(lightPixel, right); for(int i=0;i<SHADOW_RUNS;i++) { //TODO: this can be much faster methinks real r = random(seed)*2-1; real u = random(seed)*sqrt(1-r*r); movedLightRay.ray = fast_normalize(lightVector+right*r*light->radius+up*u*light->radius); ItemPtr closestItem = getClosestItem(movedLightRay); if(closestItem!=NULL && closestItem->type==LIGHT) { hitLight++; } } if(hitLight > 0) { real lightValue = ((real)hitLight) / SHADOW_RUNS; if(diffuseFactor>0) { diffuseFactor *= lightValue; diffuseColor = diffuseColor+light->light*diffuseFactor; } if(specularFactor>0) { specularFactor = lightValue * pow(specularFactor, specularRoughness); specularColor = specularColor+light->light*specularFactor; } } } } } Vector color = (diffuseColor*getDiffuse(item, point)+specularColor*getSpecular(item, point)) * magnitude; if(depth > 0) { Ray refraction; if(getRefraction(item, point)) { refraction.ray = refract(ray.ray, normal, item, refractiveIndex); refraction.from = point+(refraction.ray*.001f); if(length2(refraction.ray)>0) { push(stack, depth-1, refraction, magnitude, getRefraction(item, point)); } } if(getReflection(item, point) > 0) { push(stack, depth-1, reflection, magnitude * getReflection(item, point), refractiveIndex); } } return color; }