/// <summary> /// Metoda koja pomocu pracenja zrake racuna boju u tocki presjeka. Racuna se /// osvjetljenje u tocki presjeka te se zbraja s doprinosima osvjetljenja koje /// donosi reflektirana i refraktirana zraka. /// </summary> /// <param name="ray">pracena zraka</param> /// <param name="depth">dubina rekurzije</param> /// <returns>vektor boje u tocki presjeka</returns> public ColorVector traceRay(Ray ray, int depth) { ColorVector Clocal = backgroundColors; ColorVector C = new ColorVector(0, 0, 0); int tocka_najblizeg_presjeka = -1; bool presjek = false; if (depth > MAXDEPTH) { C = new ColorVector(0, 0, 0); return(C); } else { for (int i = 0; i < this.numberOfObjects; i++) { if (sphere[i].intersection(ray)) { presjek = true; if (tocka_najblizeg_presjeka == -1) { tocka_najblizeg_presjeka = i; } if (ray.getStartingPoint().getDistanceFrom(sphere[tocka_najblizeg_presjeka].getIntersectionPoint()) > ray.getStartingPoint().getDistanceFrom(sphere[i].getIntersectionPoint())) { tocka_najblizeg_presjeka = i; } } } if (presjek) { PropertyVector ambijetalniKoef = sphere[tocka_najblizeg_presjeka].getKa(); double r, g, b, pom; r = ambientLight.getRed() * ambijetalniKoef.getRedParameter(); g = ambientLight.getGreen() * ambijetalniKoef.getGreenParameter(); b = ambientLight.getBlue() * ambijetalniKoef.getBlueParameter(); Clocal = new ColorVector((float)r, (float)g, (float)b); Point najblizatocka = sphere[tocka_najblizeg_presjeka].getIntersectionPoint(); PropertyVector difuzniKoef = sphere[tocka_najblizeg_presjeka].getKd(); Vector L = new Vector(najblizatocka, lightPosition); Vector N = sphere[tocka_najblizeg_presjeka].getNormal(najblizatocka); Vector V = new Vector(najblizatocka, ray.getStartingPoint()); Vector R = L.getReflectedVector(N); V.normalize(); R.normalize(); L.normalize(); double ni = sphere[tocka_najblizeg_presjeka].getNi(); double vn = V.dotProduct(N); if (vn < 0) { N = N.multiple(-1); ni = 1.0 / ni; } bool sjena = shadow(najblizatocka); if ((pom = L.dotProduct(N)) > 0 && !sjena) { r = light.getRed() * difuzniKoef.getRedParameter() * pom; g = light.getGreen() * difuzniKoef.getGreenParameter() * pom; b = light.getBlue() * difuzniKoef.getBlueParameter() * pom; ColorVector Cdifuzno = new ColorVector((float)r, (float)g, (float)b); Clocal = Clocal.add(Cdifuzno); } PropertyVector spekularniKoef = sphere[tocka_najblizeg_presjeka].getKs(); if ((pom = R.dotProduct(V)) > 0 && !sjena) { r = light.getRed() * spekularniKoef.getRedParameter() * Math.Pow(pom, sphere[tocka_najblizeg_presjeka].getN()); g = light.getGreen() * spekularniKoef.getGreenParameter() * Math.Pow(pom, sphere[tocka_najblizeg_presjeka].getN()); b = light.getBlue() * spekularniKoef.getBlueParameter() * Math.Pow(pom, sphere[tocka_najblizeg_presjeka].getN()); ColorVector Cspekularno = new ColorVector((float)r, (float)g, (float)b); Clocal = Clocal.add(Cspekularno); } Vector ReflektiraniV = V.getReflectedVector(N); ReflektiraniV.normalize(); Ray Rrefl = new Ray(najblizatocka, ReflektiraniV); ColorVector Crefl = traceRay(Rrefl, depth + 1); Vector U = V.getRefractedVector(N, ni); U.normalize(); Ray Rrefr = new Ray(najblizatocka, U); ColorVector Crefr = traceRay(Rrefr, depth + 1); C = C.add(Clocal); C = C.add(Crefl.multiple(sphere[tocka_najblizeg_presjeka].getReflectionFactor())); C = C.add(Crefr.multiple(sphere[tocka_najblizeg_presjeka].getRefractionFactor())); C.correct(); return(C); } else { return(C = new ColorVector(backgroundColors.getRed(), backgroundColors.getBlue(), backgroundColors.getGreen())); } } }
/// <summary> /// Sluzi za mnozenje vektora boje s vektorom koeficijenata. Koristi se kod /// odredivanja boje lokalnog osvjetljenja. /// </summary> /// <param name="c">vektor koeficijenata s kojim se mnozi</param> /// <returns>vektor boje koji je rezultat mnozenja vektora boje s vektorom koeficijenata</returns> public ColorVector multiple(PropertyVector c) { return(new ColorVector(c.getRedParameter() * red, c.getGreenParameter() * green, c.getBlueParameter() * blue)); }