SphereFlake.cc

Go to the documentation of this file.
00001 #include <gra/scene/SphereFlake.h>
00002 #include <esg/PointLight.h>
00003 #include <esg/geometry/Sphere.h>
00004 #include <esg/geometry/Polygon.h>
00005 #include <esg/geometry/Triangle.h>
00006 
00007 using namespace gra;
00008 
00009 void SphereFlake::_create_lights()
00010 {
00011     (void) appendLight(new PointLight(Vector3( 4.00000, 3.00000, 2.00000),
00012                                       Vector3( 0.57735, 0.57735, 0.57735)));
00013     (void) appendLight(new PointLight(Vector3( 1.00000,-4.00000, 4.00000),
00014                                       Vector3( 0.57735, 0.57735, 0.57735)));
00015     (void) appendLight(new PointLight(Vector3(-3.00000, 1.00000, 5.00000),
00016                                       Vector3( 0.57735, 0.57735, 0.57735)));
00017 }
00018 
00019 AutoPtr<Material>** SphereFlake::_create_materials(unsigned& numMats)
00020 {
00021     Color3f color(1.0, 0.9, 0.7);
00022 
00023     Color3f ambient(color);
00024     Color3f diffuse(color);
00025     Color3f specular(color);
00026     Color3f reflection(color);
00027 
00028     ambient.scale(0.0);
00029     diffuse.scale(0.5);
00030     specular.scale(0.5);
00031     reflection.scale(0.5);
00032 
00033     //float roughness  = log(0.5) / log(cos(PI * 37.0 / 180.0));
00034     float roughness = .04;
00035 
00036     numMats = 5;
00037     AutoPtr<Material>** materials = new AutoPtr<Material>* [numMats];
00038 
00039     materials[0] = new AutoPtr<Material>(new Ambient(ambient));
00040     materials[1] = new AutoPtr<Material>(new Diffuse(diffuse));
00041     materials[2] = new AutoPtr<Material>(new Specular(specular));
00042     materials[3] = new AutoPtr<Material>(new Roughness(roughness));
00043     materials[4] = new AutoPtr<Material>(new Reflection(reflection));
00044 
00045     return materials;
00046 }
00047 
00048 void SphereFlake::_create_object_set(Vector3 objset[9])
00049 {
00050     /*
00051      * Create the set of 9 vectors needed to generate the sphere set.
00052      * Uses global 'objset'
00053      */
00054 
00055     Vector3 axis, trio_dir[3];
00056     double  dist;
00057     Matrix4 mx;
00058         
00059     dist = 1.0 / sqrt((double)2.0);
00060         
00061     trio_dir[0].set(dist, dist,   0.0);
00062     trio_dir[1].set(dist,  0.0, -dist);
00063     trio_dir[2].set( 0.0, dist, -dist);
00064         
00065     axis.set(dist, -dist, 0.0);
00066     
00067     mx.rotationGL(asin((double)(2.0/sqrt((double)6.0))), axis);
00068         
00069     for (int i = 0; i < 3; i++) mx.transform(trio_dir[i]);
00070         
00071     for (int i = 0; i < 3; i++) {
00072         mx.rotZ(i*2.0*PI/3.0);
00073         for (int j = 0; j < 3; j++) mx.transform(trio_dir[j], objset[i*3+j]);
00074     }
00075 }
00076 
00077 void SphereFlake::_create_spheres(unsigned            depth,
00078                                   const Vector4&      center,
00079                                   const Vector4&      direction,
00080                                   Vector3             objset[9],
00081                                   AutoPtr<Material>** materials,
00082                                   unsigned            numMats)
00083 {
00084     /*
00085      * Output the parent sphere, then output the children of the sphere.
00086      */
00087 
00088     double   angle, scale;
00089     Matrix4  mx;
00090     Vector3  axis, z_axis;
00091     Vector4  child_pt, child_dir;
00092 
00093     Shape* pSphere = new Shape(_lastOID++, NULL);
00094     pSphere->setPrivateGeometry(new Sphere(center.x,
00095                                            center.y,
00096                                            center.z,
00097                                            center.w));
00098     for (unsigned i = 0; i < numMats; i++)
00099         pSphere->appendSharedMaterial(materials[i]);
00100 
00101     (void) appendObject(pSphere);
00102 
00103     /* check if children should be generated */
00104     if (depth > 0) {
00105         --depth;
00106                 
00107         /* rotation matrix to new axis from +Z axis */
00108         if (direction.z >= 1.0) {
00109             mx.setIdentity();
00110         } else if (direction.z <= -1.0) {
00111             mx.rotY(PI);
00112         } else {
00113             Vector3 aux(direction.x, direction.y, direction.z);
00114             z_axis.set(0.0, 0.0, 1.0);
00115             axis.cross(z_axis, aux);
00116             axis.normalize();
00117             angle = acos((double) z_axis.dot(aux));
00118             mx.rotationGL(angle, axis);
00119         }
00120 
00121         /* scale down location of new spheres */
00122         scale = center.w * (1.0 + direction.w);
00123 
00124         for (int i = 0 ; i < 9 ; i++) {
00125             mx.transform(objset[i], child_pt);
00126             child_pt.scaleAdd(scale, center);
00127             /* scale down radius */
00128             child_pt.w = center.w * direction.w;
00129             child_dir.set(child_pt);
00130             child_dir.sub(center);
00131             child_dir.x /= scale;
00132             child_dir.y /= scale;
00133             child_dir.z /= scale;
00134             child_dir.w = direction.w;
00135             _create_spheres(depth,child_pt,child_dir,objset,materials,numMats);
00136         }
00137     }
00138 }
00139 
00140 SphereFlake::SphereFlake(const SDS & proto, unsigned factor, float radius)
00141     : Scene(proto)
00142 {
00143     Vector3 objset[9];
00144     Vector4 center(0.0, 0.0, 0.0, radius/2.0);
00145     Vector4 direction(0.0, 0.0, 1.0, 1.0/3.0);
00146     
00147     AutoPtr<Material>** materials;
00148     unsigned            numMats;
00149 
00150     materials = _create_materials(numMats);
00151     _create_object_set(objset);
00152     _create_spheres(factor, center, direction, objset, materials, numMats);
00153     _create_lights();
00154 
00155     delete [] materials;
00156 
00157     /*
00158      * floor polygon
00159      */
00160     Vector3 bvec(12.0 * radius, 12.0 * radius, -radius / 2.0);
00161     Vector3 vert[4];
00162     Color3f color(1.0, 0.75, 0.33);
00163 
00164     Color3f ambient(color);  ambient.scale(0.2);
00165     Color3f diffuse(color);  diffuse.scale(0.8);
00166     Color3f specular(color); specular.scale(0.0);
00167     float   roughness  = 100000.0;
00168 
00169 #if 0
00170     vert[0].set( bvec.x, bvec.y, bvec.z);
00171     vert[1].set(-bvec.x,-bvec.y, bvec.z);
00172     vert[2].set( bvec.x,-bvec.y, bvec.z);
00173     
00174     Shape * pFloor = new Shape(_lastOID++, NULL);
00175     pFloor->setPrivateGeometry(new Triangle(vert, NULL, NULL,
00176                                             Vector3(0,0,1), true));
00177     
00178     pFloor->appendPrivateMaterial(new Ambient(ambient));
00179     pFloor->appendPrivateMaterial(new Diffuse(diffuse));
00180     pFloor->appendPrivateMaterial(new Specular(specular));
00181     pFloor->appendPrivateMaterial(new Roughness(roughness));
00182 
00183     vert[0].set( bvec.x, bvec.y, bvec.z);
00184     vert[1].set(-bvec.x, bvec.y, bvec.z);
00185     vert[2].set(-bvec.x,-bvec.y, bvec.z);
00186 
00187     (void) appendObject(pFloor);
00188 
00189     pFloor = new Shape(_lastOID++, NULL);
00190     pFloor->setPrivateGeometry(new Triangle(vert, NULL, NULL,
00191                                             Vector3(0,0,1), true));
00192     
00193     pFloor->appendPrivateMaterial(new Ambient(ambient));
00194     pFloor->appendPrivateMaterial(new Diffuse(diffuse));
00195     pFloor->appendPrivateMaterial(new Specular(specular));
00196     pFloor->appendPrivateMaterial(new Roughness(roughness));
00197 
00198     (void) appendObject(pFloor);
00199 #endif
00200 
00201 #if 1
00202     vert[0].set( bvec.x, bvec.y, bvec.z);
00203     vert[1].set(-bvec.x, bvec.y, bvec.z);
00204     vert[2].set(-bvec.x,-bvec.y, bvec.z);
00205     vert[3].set( bvec.x,-bvec.y, bvec.z);
00206     
00207     Shape * pFloor = new Shape(_lastOID++, NULL);
00208     pFloor->setPrivateGeometry(new Polygon(vert,NULL,NULL,4,Vector3(0,0,1),true));
00209     
00210     pFloor->appendPrivateMaterial(new Ambient(ambient));
00211     pFloor->appendPrivateMaterial(new Diffuse(diffuse));
00212     pFloor->appendPrivateMaterial(new Specular(specular));
00213     pFloor->appendPrivateMaterial(new Roughness(roughness));
00214 
00215     (void) appendObject(pFloor);
00216 #endif
00217 
00218     build();
00219 }

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