CornellBox.cc

Go to the documentation of this file.
00001 #include <gra/scene/CornellBox.h>
00002 #include <esg/geometry/Polygon.h>
00003 #include <esg/geometry/Rectangle.h>
00004 #include <esg/DirLight.h>
00005 #include <esg/Material.h>
00006 #include <esg/RefrCoefs.h>
00007 
00008 using namespace gra;
00009 
00010 #define KB_CORNER 1.0
00011 
00012 const int     CornellBox::_upperLeftFar   = 0;
00013 const int     CornellBox::_upperLeftNear  = 1;
00014 const int     CornellBox::_upperRightNear = 2;
00015 const int     CornellBox::_upperRightFar  = 3;
00016 const int     CornellBox::_lowerLeftNear  = 4;
00017 const int     CornellBox::_lowerLeftFar   = 5;
00018 const int     CornellBox::_lowerRightFar  = 6;
00019 const int     CornellBox::_lowerRightNear = 7;
00020 
00021 const float   CornellBox::_lightScale = .35;
00022 
00023 const Vector3 CornellBox::_box [8] = {
00024     Vector3(-KB_CORNER, KB_CORNER,-KB_CORNER),
00025     Vector3(-KB_CORNER, KB_CORNER, KB_CORNER),
00026     Vector3( KB_CORNER, KB_CORNER, KB_CORNER),
00027     Vector3( KB_CORNER, KB_CORNER,-KB_CORNER),
00028     Vector3(-KB_CORNER,-KB_CORNER, KB_CORNER),
00029     Vector3(-KB_CORNER,-KB_CORNER,-KB_CORNER),
00030     Vector3( KB_CORNER,-KB_CORNER,-KB_CORNER),
00031     Vector3( KB_CORNER,-KB_CORNER, KB_CORNER)
00032 };
00033 
00034 void CornellBox::_build_walls()
00035 {
00036     Vector3 wLeft [4] = { _box[_lowerLeftFar], 
00037                           _box[_lowerLeftNear],
00038                           _box[_upperLeftNear],
00039                           _box[_upperLeftFar] };
00040     Vector3 wFront [4] = { _box[_lowerLeftNear], 
00041                            _box[_lowerRightNear],
00042                            _box[_upperRightNear],
00043                            _box[_upperLeftNear] };
00044     Vector3 wRight [4] = { _box[_lowerRightNear], 
00045                            _box[_lowerRightFar],
00046                            _box[_upperRightFar],
00047                            _box[_upperRightNear] };
00048     Vector3 wBack [4] = { _box[_lowerRightFar], 
00049                           _box[_lowerLeftFar],
00050                           _box[_upperLeftFar],
00051                           _box[_upperRightFar] };
00052     Vector3 wTop [4] = { _box[_upperLeftNear], 
00053                          _box[_upperRightNear],
00054                          _box[_upperRightFar],
00055                          _box[_upperLeftFar] };
00056     Vector3 wBottom [4] = { _box[_lowerLeftNear], 
00057                             _box[_lowerLeftFar],
00058                             _box[_lowerRightFar],
00059                             _box[_lowerRightNear] };
00060     
00061     
00062     Shape * pWall;
00063 
00064     pWall = new Shape(++_lastOID, "Left Wall");
00065     pWall->setPrivateGeometry(new esg::Polygon(wLeft, NULL, NULL, 4,
00066                                           Vector3(1,0,0), true));
00067     pWall->appendPrivateMaterial(new Specular(0,0,0));
00068     pWall->appendPrivateMaterial(new Diffuse(1.,.0,.0));
00069     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00070     //pWall->appendPrivateMaterial(new Reflection(1.));
00071     appendObject(pWall);
00072 
00073     pWall = new Shape(++_lastOID, "Front Wall");
00074     pWall->setPrivateGeometry(new esg::Polygon(wFront, NULL, NULL, 4,
00075                                           Vector3(0,0,-1), true));
00076     pWall->appendPrivateMaterial(new Specular(0,0,0));
00077     pWall->appendPrivateMaterial(new Diffuse(.0,.0,.0));
00078     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00079     //pWall->appendPrivateMaterial(new Reflection(1.));
00080     appendObject(pWall);
00081 
00082     pWall = new Shape(++_lastOID, "Right Wall");
00083     pWall->setPrivateGeometry(new esg::Polygon(wRight, NULL, NULL, 4,
00084                                           Vector3(-1,0,0), true));
00085     pWall->appendPrivateMaterial(new Specular(0,0,0));
00086     pWall->appendPrivateMaterial(new Diffuse(.0,.0,1.));
00087     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00088     //pWall->appendPrivateMaterial(new Reflection(1.));
00089     appendObject(pWall);
00090     
00091     pWall = new Shape(++_lastOID, "Back Wall");
00092     pWall->setPrivateGeometry(new esg::Polygon(wBack, NULL, NULL, 4,
00093                                           Vector3(0,0,1), true));
00094     pWall->appendPrivateMaterial(new Specular(0,0,0));
00095     pWall->appendPrivateMaterial(new Diffuse(1.,1.,1.));
00096     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00097     //pWall->appendPrivateMaterial(new Reflection(1.));
00098     appendObject(pWall);
00099 
00100     pWall = new Shape(++_lastOID, "Top Wall");
00101     pWall->setPrivateGeometry(new esg::Polygon(wTop, NULL, NULL, 4,
00102                                           Vector3(0,-1,0), true));
00103     pWall->appendPrivateMaterial(new Specular(0,0,0));
00104     pWall->appendPrivateMaterial(new Diffuse(1.,1.,1.));
00105     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00106     //pWall->appendPrivateMaterial(new Reflection(1.));
00107     appendObject(pWall);
00108     
00109     pWall = new Shape(++_lastOID, "Bottom Wall");
00110     pWall->setPrivateGeometry(new esg::Polygon(wBottom, NULL, NULL, 4,
00111                                           Vector3(0,1,0), true));
00112     pWall->appendPrivateMaterial(new Specular(0,0,0));
00113     pWall->appendPrivateMaterial(new Diffuse(1.,1.,1.));
00114     pWall->appendPrivateMaterial(new Ambient(0,0,0));
00115     //pWall->appendPrivateMaterial(new Reflection(1.));
00116     appendObject(pWall);
00117 }
00118 
00119 void CornellBox::_build_lights()
00120 {
00121     Vector3 lp(_box[_upperLeftNear]);
00122     lp.add(_box[_upperRightFar]);
00123     lp.scale(.5);
00124     lp.y = KB_CORNER - .01;
00125 
00126     Vector3 ud(_box[_upperRightNear]);
00127     ud.sub(_box[_upperLeftNear]);
00128     ud.scale(_lightScale);
00129 
00130     Vector3 vd(_box[_upperRightNear]);
00131     vd.sub(_box[_upperRightFar]);
00132     vd.scale(_lightScale);
00133 
00134     Vector3 cp(lp);
00135     cp.x -= ud.length() / 2.;
00136     cp.z -= vd.length() / 2.;
00137     cp.y += .005;
00138 
00139     cp.z -= .4;
00140 
00141     DirLight * pLight = new DirLight(lp,
00142                                      Vector3(0,-1,0),
00143                                      Vector3(1,1,1),
00144                                      0, // fade distance
00145                                      1.5, // fade power
00146                                      ++_lastOID,
00147                                      "Light Source");
00148     pLight->setPrivateGeometry(new esg::Rectangle(cp, ud, vd,
00149                                                   NULL,
00150                                                   true,
00151                                                   Vector3(0,-1,0)));
00152     appendLight(pLight);
00153 }
00154 
00155 void CornellBox::_create_sf_object_set(Vector3 objset[9])
00156 {
00157     /*
00158      * Create the set of 9 vectors needed to generate the sphere set.
00159      * Uses global 'objset'
00160      */
00161 
00162     Vector3 axis, trio_dir[3];
00163     double  dist;
00164     Matrix4 mx;
00165         
00166     dist = 1.0 / sqrt((double)2.0);
00167         
00168     trio_dir[0].set(dist, dist,   0.0);
00169     trio_dir[1].set(dist,  0.0, -dist);
00170     trio_dir[2].set( 0.0, dist, -dist);
00171         
00172     axis.set(dist, -dist, 0.0);
00173     
00174     mx.rotationGL(asin((double)(2.0/sqrt((double)6.0))), axis);
00175         
00176     for (int i = 0; i < 3; i++) mx.transform(trio_dir[i]);
00177         
00178     for (int i = 0; i < 3; i++) {
00179         mx.rotZ(i*2.0*PI/3.0);
00180         for (int j = 0; j < 3; j++) mx.transform(trio_dir[j], objset[i*3+j]);
00181     }
00182 }
00183 
00184 void CornellBox::_build_sphere_flake(unsigned       depth,
00185                                      const Vector4& center,
00186                                      const Vector4& direction,
00187                                      Vector3        objset[9])
00188 {
00189     double   angle, scale;
00190     Matrix4  mx;
00191     Vector3  axis, z_axis;
00192     Vector4  child_pt, child_dir;
00193 
00194     Shape* pSphere = new Shape(++_lastOID, NULL);
00195     pSphere->setPrivateGeometry(new Sphere(center.x,
00196                                            center.y,
00197                                            center.z,
00198                                            center.w));
00199     
00200     pSphere->appendPrivateMaterial(new Specular(0,0,0));
00201     pSphere->appendPrivateMaterial(new Diffuse(0,0,0));
00202     pSphere->appendPrivateMaterial(new Ambient(0,0,0));
00203     //pSphere->appendPrivateMaterial(new Reflection(.12,.12,.12));
00204     //pSphere->appendPrivateMaterial(new Transparency(.88,.88,.88));
00205     pSphere->appendPrivateMaterial(new Transparency(1,1,1));
00206     pSphere->appendPrivateMaterial(new Roughness((float).3));
00207     pSphere->appendPrivateMaterial(new IndexOfRefraction(REFR_GLASS));
00208     (void) appendObject(pSphere);
00209 
00210     /* check if children should be generated */
00211     if (depth > 0) {
00212         --depth;
00213                 
00214         /* rotation matrix to new axis from +Z axis */
00215         if (direction.z >= 1.0) {
00216             mx.setIdentity();
00217         } else if (direction.z <= -1.0) {
00218             mx.rotY(PI);
00219         } else {
00220             Vector3 aux(direction.x, direction.y, direction.z);
00221             z_axis.set(0.0, 0.0, 1.0);
00222             axis.cross(z_axis, aux);
00223             axis.normalize();
00224             angle = acos((double) z_axis.dot(aux));
00225             mx.rotationGL(angle, axis);
00226         }
00227 
00228         /* scale down location of new spheres */
00229         scale = center.w * (1.0 + direction.w);
00230 
00231         for (int i = 0 ; i < 9 ; i++) {
00232             mx.transform(objset[i], child_pt);
00233             child_pt.scaleAdd(scale, center);
00234             /* scale down radius */
00235             child_pt.w = center.w * direction.w;
00236             child_dir.set(child_pt);
00237             child_dir.sub(center);
00238             child_dir.x /= scale;
00239             child_dir.y /= scale;
00240             child_dir.z /= scale;
00241             child_dir.w = direction.w;
00242             _build_sphere_flake(depth,child_pt,child_dir,objset);
00243         }
00244     }
00245 }
00246 
00247 
00248 CornellBox::CornellBox(const SDS & proto)
00249     : Scene(proto)
00250 {
00251     //float radius = .32;
00252     
00253     _build_walls();
00254     _build_lights();
00255 }
00256 
00257 void CornellBox::addMirrorSphere(float radius)
00258 {
00259     Shape * pSphere = new Shape(++_lastOID, "Mirror Sphere");
00260     pSphere->setPrivateGeometry(new Sphere(-.51, radius-KB_CORNER,-.5,radius));
00261     pSphere->appendPrivateMaterial(new Specular(0,0,0));
00262     pSphere->appendPrivateMaterial(new Diffuse(0,0,0));
00263     pSphere->appendPrivateMaterial(new Ambient(0,0,0));
00264     pSphere->appendPrivateMaterial(new Reflection(1.,1.,1.));
00265     pSphere->appendPrivateMaterial(new Roughness((float)0.04));
00266     appendObject(pSphere);
00267 }
00268 
00269 void CornellBox::addCrystalicSphere(float radius)
00270 {
00271     Shape * pSphere = new Shape(++_lastOID, "Crystalic Sphere");
00272     pSphere->setPrivateGeometry(new Sphere(.53, radius-KB_CORNER,-.1,radius));
00273     pSphere->appendPrivateMaterial(new Specular(0,0,0));
00274     pSphere->appendPrivateMaterial(new Diffuse(0,0,0));
00275     pSphere->appendPrivateMaterial(new Ambient(0,0,0));
00276     pSphere->appendPrivateMaterial(new Transparency(1,1,1));
00277     pSphere->appendPrivateMaterial(new Roughness((float).3));
00278     pSphere->appendPrivateMaterial(new IndexOfRefraction(REFR_GLASS));
00279     appendObject(pSphere);
00280 }
00281 
00282 void CornellBox::addSphereFlake(unsigned factor, float radius)
00283 {
00284     Vector3 objset[9];
00285     Vector4 center(0.0, 0.0, 0.0, radius/2.0);
00286     Vector4 direction(0.0, 0.0, 1.0, 1.0/3.0);
00287     
00288     _create_sf_object_set(objset);
00289     _build_sphere_flake(factor, center, direction, objset);
00290 }

Generated on Tue Nov 21 15:11:42 2006 for gra by  doxygen 1.4.6