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
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
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
00117
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
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
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
00173 half_width = width>>1;
00174 hside_length = (double)half_width * _width / fnum_pts;
00175 rise_height = hside_length * _roughness;
00176
00177
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
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