FractalMount.cc

Go to the documentation of this file.
00001 #include <gra/scene/FractalMount.h>
00002 #include <esg/PointLight.h>
00003 #include <esg/geometry/Sphere.h>
00004 #include <esg/geometry/Polygon.h>
00005 
00006 using namespace gra;
00007 
00008 void FractalMount::_create_lights()
00009 {
00010     (void) appendLight(new PointLight(Vector3(-100.0, -100.0, 100.0),
00011                                       Vector3(1.0, 1.0, 1.0)));
00012 }
00013 
00014 AutoPtr<Material>** FractalMount::_create_crystal_materials(unsigned& numMats)
00015 {
00016     Color3f color(0.9, 0.9, 0.9);
00017 
00018     Color3f ambient(color);
00019     Color3f diffuse(color);
00020     Color3f specular(color);
00021     Color3f transparency(color);
00022     Color3f reflection(.1,.1,.1);
00023 
00024     ambient.scale(0.0);
00025     diffuse.scale(0.1);
00026     specular.scale(0.4);
00027     transparency.scale(1.0);
00028 
00029     //float roughness  = log(0.5) / log(cos(PI * 37.0 / 180.0));
00030     float roughness  = .5;
00031     float refrIndex  = 1.5;
00032 
00033     numMats = 7;
00034     AutoPtr<Material>** materials = new AutoPtr<Material>* [numMats];
00035 
00036     materials[0] = new AutoPtr<Material>(new Ambient(ambient));
00037     materials[1] = new AutoPtr<Material>(new Diffuse(diffuse));
00038     materials[2] = new AutoPtr<Material>(new Specular(specular));
00039     materials[3] = new AutoPtr<Material>(new IndexOfRefraction(refrIndex));
00040     materials[4] = new AutoPtr<Material>(new Roughness(roughness));
00041     materials[5] = new AutoPtr<Material>(new Transparency(transparency));
00042     materials[6] = new AutoPtr<Material>(new Reflection(reflection));
00043 
00044     return materials;
00045 }
00046 
00047 AutoPtr<Material>** FractalMount::_create_mount_materials(unsigned& numMats)
00048 {
00049     Color3f color(0.5, 0.45, 0.35);
00050     Color3f ambient(color);  ambient.scale(0.0);
00051     Color3f diffuse(color);  diffuse.scale(1.0);
00052     Color3f specular(color); specular.scale(0.0);
00053 
00054     numMats = 4;
00055     AutoPtr<Material>** materials = new AutoPtr<Material>* [numMats];
00056 
00057     materials[0] = new AutoPtr<Material>(new Ambient(ambient));
00058     materials[1] = new AutoPtr<Material>(new Diffuse(diffuse));
00059     materials[2] = new AutoPtr<Material>(new Specular(specular));
00060     materials[3] = new AutoPtr<Material>(new Roughness((float)_roughness));
00061 
00062     return materials;
00063 }
00064 
00065 void FractalMount::_create_spheres(const Vector4&      center,
00066                                  AutoPtr<Material>** materials,
00067                                  unsigned            numMats)
00068                                  
00069 {
00070     double  angle;
00071     double  radius = center.w;
00072     Vector3 axis, pt, new_pt;
00073     Vector3 sphere;
00074     Matrix4 mx;
00075 
00076     axis.set(1.0, 1.0, 0.0);
00077     axis.normalize();
00078     angle = acos((double)(-1.0/3.0));
00079         
00080     /* set center of pyramid */
00081     pt.set(0., 0., radius * sqrt((double)(3.0/2.0)));
00082 
00083     sphere.set(center.x, center.y, center.z);
00084     sphere.add(pt);
00085 
00086     Shape* pSphere = new Shape(_lastOID++, NULL);
00087     pSphere->setPrivateGeometry(new Sphere(sphere.x,
00088                                            sphere.y,
00089                                            sphere.z,
00090                                            radius));
00091     for (unsigned j = 0; j < numMats; j++)
00092         pSphere->appendSharedMaterial(materials[j]);
00093     (void) appendObject(pSphere);
00094 
00095     mx.rotationGL(angle, axis);
00096     mx.transform(pt, new_pt);
00097         
00098     for (unsigned i = 0; i < 3; i++) {
00099         mx.rotZ((double)i * 2.0 * PI / 3.0);
00100         mx.transform(new_pt, sphere);
00101         sphere.x += center.x;
00102         sphere.y += center.y;
00103         sphere.z += center.z;
00104         pSphere = new Shape(_lastOID++, NULL);
00105         pSphere->setPrivateGeometry(new Sphere(sphere.x,
00106                                                sphere.y,
00107                                                sphere.z,
00108                                                radius));
00109         for (unsigned j = 0; j < numMats; j++)
00110             pSphere->appendSharedMaterial(materials[j]);
00111         (void) appendObject(pSphere);
00112     }
00113 }
00114 
00115 /*
00116  * Build mountain section.  If at width > 1, split quadrilateral into four
00117  * parts.  Else if at width == 1, output quadrilateral as two triangles.
00118  */
00119 void FractalMount::_grow_mountain(double fnum_pts,
00120                                 int    width,
00121                                 int    ll_x,
00122                                 int    ll_y,
00123                                 double ll_fz,
00124                                 double lr_fz,
00125                                 double ur_fz,
00126                                 double ul_fz,
00127                                 AutoPtr<Material>** materials,
00128                                 unsigned            numMats)
00129 {
00130     long    iz;
00131     int     half_width, num_tri, num_tri_vert, num_vert, h1, h2;
00132     double  l_fx, r_fx, l_fy, u_fy;
00133     double  lower_fz, right_fz, upper_fz, left_fz, middle_fz;
00134     double  rise_height, hside_length;
00135     double  gauss_rand;
00136     Vector3 tri_vert[3];
00137     Vector3 normal,e1,e2;
00138 
00139     if (width == 1) {
00140         /* calculate x and y coordinates of corners */
00141         l_fx = _xCorner + (double)ll_x     * _width / fnum_pts;
00142         r_fx = _xCorner + (double)(ll_x+1) * _width / fnum_pts;
00143         l_fy = _yCorner + (double)ll_y     * _width / fnum_pts;
00144         u_fy = _yCorner + (double)(ll_y+1) * _width / fnum_pts;
00145 
00146         /* output two triangles for section */
00147         for (num_tri = 0; num_tri < 2; num_tri++) {
00148             for (num_vert = 0; num_vert < 3; num_vert++) {
00149                 num_tri_vert = (num_vert + num_tri * 2) % 4;
00150                 switch (num_tri_vert) {
00151                 case 0:
00152                     tri_vert[num_vert].set(l_fx, l_fy, ll_fz); break;
00153                 case 1:
00154                     tri_vert[num_vert].set(r_fx, l_fy, lr_fz); break;
00155                 case 2:
00156                     tri_vert[num_vert].set(r_fx, u_fy, ur_fz); break;
00157                 case 3:
00158                     tri_vert[num_vert].set(l_fx, u_fy, ul_fz); break;
00159                 }
00160             }
00161             e1.set(tri_vert[2]); e1.sub(tri_vert[1]); e1.normalize();
00162             e2.set(tri_vert[0]); e2.sub(tri_vert[1]); e2.normalize();
00163             normal.cross(e1, e2);
00164             Shape * pPolygon = new Shape(_lastOID++, NULL);
00165             pPolygon->setPrivateGeometry(new esg::Polygon(tri_vert, NULL, NULL,
00166                                                      3, normal, true));
00167             for (unsigned i = 0; i < numMats; i++)
00168                 pPolygon->appendSharedMaterial(materials[i]);
00169             (void) appendObject(pPolygon);
00170         }
00171     } else {
00172         /* subdivide edges and move them in z direction */
00173         half_width = width>>1;
00174         hside_length = (double)half_width * _width / fnum_pts;
00175         rise_height = hside_length * _roughness;
00176 
00177         /* for each midpoint, find z */
00178         h1 = ll_x + half_width;
00179         h2 = ll_y;
00180         ESG_HASH_RAND(h1, h2, _factor, iz);
00181         iz += _mountainNo;
00182         ESG_GAUSS_RAND(iz, gauss_rand);
00183         lower_fz = (ll_fz + lr_fz) / 2.0 + rise_height * gauss_rand;
00184 
00185         h1 = ll_x + width;
00186         h2 = ll_y + half_width;
00187         ESG_HASH_RAND(h1, h2, _factor, iz);
00188         iz += _mountainNo;
00189         ESG_GAUSS_RAND(iz, gauss_rand);
00190         right_fz = (lr_fz + ur_fz) / 2.0 + rise_height * gauss_rand;
00191 
00192         h1 = ll_x + half_width;
00193         h2 = ll_y + width;
00194         ESG_HASH_RAND(h1, h2, _factor, iz);
00195         iz += _mountainNo;
00196         ESG_GAUSS_RAND(iz, gauss_rand);
00197         upper_fz = (ur_fz + ul_fz) / 2.0 + rise_height * gauss_rand;
00198 
00199         h1 = ll_x;
00200         h2 = ll_y + half_width;
00201         ESG_HASH_RAND(h1, h2, _factor, iz);
00202         iz += _mountainNo;
00203         ESG_GAUSS_RAND(iz, gauss_rand);
00204         left_fz = (ul_fz + ll_fz) / 2.0 + rise_height * gauss_rand;
00205 
00206         h1 = ll_x + half_width;
00207         h2 = ll_y + half_width;
00208         ESG_HASH_RAND(h1, h2, _factor, iz);
00209         iz += _mountainNo;
00210         ESG_GAUSS_RAND(iz, gauss_rand);
00211         middle_fz = ((ll_fz + lr_fz + ur_fz + ul_fz) /
00212                      4.0 + 1.4142136 * rise_height * gauss_rand);
00213         
00214         /* check subsections for subdivision or output */
00215         _grow_mountain(fnum_pts, half_width, ll_x, ll_y,
00216                        ll_fz, lower_fz, middle_fz, left_fz,
00217                        materials, numMats);
00218         _grow_mountain(fnum_pts, half_width, ll_x+half_width, ll_y,
00219                        lower_fz, lr_fz, right_fz, middle_fz,
00220                        materials, numMats);
00221         _grow_mountain(fnum_pts, half_width, ll_x+half_width, ll_y+half_width,
00222                        middle_fz, right_fz, ur_fz, upper_fz,
00223                        materials, numMats);
00224         _grow_mountain(fnum_pts, half_width, ll_x, ll_y+half_width,
00225                        left_fz, middle_fz, upper_fz, ul_fz,
00226                        materials, numMats);
00227     }
00228 }
00229 
00230 FractalMount::FractalMount(const SDS & proto,
00231                        unsigned        factor,
00232                        unsigned        mn,
00233                        double          xc,
00234                        double          yc,
00235                        double          w)
00236     : Scene(proto)
00237 {
00238     _factor = factor;
00239 
00240     AutoPtr<Material>** materials;
00241     unsigned            numMats;
00242     materials = _create_crystal_materials(numMats);
00243     _create_spheres(Vector4(-0.3, 0.3, 0.5, 0.15), materials, numMats);
00244 
00245     materials    = _create_mount_materials(numMats);
00246     int num_pts  = 1<<_factor;
00247     double ratio = 2.0 / exp((double)(log((double)2.0) / 1.2));
00248     _mountainNo  = mn;
00249     _xCorner     = xc;
00250     _yCorner     = yc;
00251     _width       = w;
00252     _roughness   = sqrt((double)(ratio * ratio - 1.0));
00253     
00254     _grow_mountain((double)num_pts, num_pts, 0, 0, 0.0, 0.0, 0.0, 0.0,
00255                    materials, numMats);
00256 
00257     _create_lights();
00258 
00259     build();
00260 }
00261                        

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