surface.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <iostream>
00021 #include <math.h>
00022 
00023 #include <archon/util/color.H>
00024 #include <archon/util/image.H>
00025 
00026 #include "surface.H"
00027 
00028 namespace Archon
00029 {
00030   using namespace Utilities;
00031   using namespace Math;
00032 
00033   namespace Raytracer
00034   {
00038     ColorRGBA Surface::shade(const Light &light, const Vector3 &normal,
00039                              const Vector3 &viewDirection, const Vector3 &lightDirection,
00040                              const ColorRGBA &surfaceColor) const
00041     {
00042       /*
00043        * Note: Phongs transmission term is not regarded.
00044        */
00045       Vector3 h = lightDirection;
00046       h += viewDirection;
00047       h /= 2;
00048 
00049       const double f = diffuseReflection * dot(lightDirection, normal);
00050       const double s = specularReflection * pow(dot(normal, h), reflectiveExponent);
00051 
00052       return Vector3(light.getColor()[0] * surfaceColor[0] * f + s,
00053                      light.getColor()[1] * surfaceColor[1] * f + s,
00054                      light.getColor()[2] * surfaceColor[2] * f + s);
00055     }
00056 
00057     inline int modulo(int x, int y)
00058     {
00059       const int v = x % y;
00060       return v < 0 ? v + y : v;
00061     }
00062 
00071     void Texture::getColor(const Vector2 &texturePoint, ColorRGBA &c) const
00072     {
00073       const int tileWidth  = image.getWidth();
00074       const int tileHeight = image.getHeight();
00075 
00076       const int width  = tileWidth  * horizontalTiles;
00077       const int height = tileHeight * verticalTiles;
00078 
00079       const double x = width  * texturePoint[0] - 0.5;
00080       const double y = height * texturePoint[1] - 0.5;
00081 
00082       // Determine indices of upper left pixel of releval 2x2 pixel box.
00083       const int xi = static_cast<int>(floor(x));
00084       const int yi = static_cast<int>(floor(y));
00085 
00086       const int x0 = modulo(xi, tileWidth);
00087       const int x1 = (x0 + 1) % tileWidth;
00088       const int y0 = modulo(yi, tileHeight);
00089       const int y1 = (y0 + 1) % tileHeight;
00090 
00091       const double xf = x - xi;
00092       const double yf = y - yi;
00093 
00094       const double k1 = (1 - xf) * (1 - yf);
00095       const double k2 = xf * (1 - yf);
00096       const double k3 = (1 - xf) * yf;
00097       const double k4 = xf * yf;
00098 
00099       ColorRGBA c1, c2, c3, c4;
00100       /*
00101         if(xi < 0)
00102         {
00103         if(yi < 0) c1 = c2 = c3 = c4 = texture->get_pixel(0, 0);
00104         else if(yi >= height - 1) c1 = c2 = c3 = c4 = texture->get_pixel(0, tileHeight - 1);
00105         else 
00106         {
00107         c1 = c2 = texture->get_pixel(0, yi % tileHeight);
00108         c3 = c4 = texture->get_pixel(0, (yi + 1) % tileHeight);
00109         }
00110         }
00111         else if(xi >= width - 1)
00112         {
00113         if(yi < 0) c1 = c2 = c3 = c4 = texture->get_pixel(tileWidth - 1, 0);
00114         else if(yi >= height - 1) c1 = c2 = c3 = c4 = texture->get_pixel(tileWidth - 1, tileHeight - 1);
00115         else
00116         {
00117         c1 = c2 = texture->get_pixel(tileWidth - 1, yi % tileHeight);
00118         c3 = c4 = texture->get_pixel(tileWidth - 1, (yi + 1) % tileHeight);
00119         }
00120         }
00121         else 
00122         {
00123         if(yi < 0) 
00124         {
00125         c1 = c3 = texture->get_pixel(xi % tileWidth, 0);
00126         c2 = c4 = texture->get_pixel((xi + 1) % tileWidth, 0);
00127         }
00128         else if(yi >= height - 1)
00129         {
00130         c1 = c3 = texture->get_pixel(xi % tileWidth, tileHeight - 1);
00131         c2 = c4 = texture->get_pixel((xi + 1) % tileWidth, tileHeight - 1);
00132         }
00133         else 
00134         {*/
00135       image.getPixel(x0, y0, c1[0], c1[1], c1[2], c1[3]);
00136       image.getPixel(x1, y0, c2[0], c2[1], c2[2], c2[3]);
00137       image.getPixel(x0, y1, c3[0], c3[1], c3[2], c3[3]);
00138       image.getPixel(x1, y1, c4[0], c4[1], c4[2], c4[3]);
00139       /*}
00140         }*/
00141 
00142       c[0] = k1 * c1[0] + k2 * c2[0] + k3 * c3[0] + k4 * c4[0];
00143       c[1] = k1 * c1[1] + k2 * c2[1] + k3 * c3[1] + k4 * c4[1];
00144       c[2] = k1 * c1[2] + k2 * c2[2] + k3 * c3[2] + k4 * c4[2];
00145       c[3] = k1 * c1[3] + k2 * c2[3] + k3 * c3[3] + k4 * c4[3];
00146     }
00147   }
00148 }
00149 

Generated on Sun Jul 30 22:55:51 2006 for Archon by  doxygen 1.4.4