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
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
00052
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
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
00104 if (depth > 0) {
00105 --depth;
00106
00107
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
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
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
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 }