00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012
00013 #include "datahash/datahash_text.h"
00014 #include "datahash/datahash_util.h"
00015 #include "geometry/geometry_3d.h"
00016 #include "geometry/matrix_4.h"
00017 #include "perf/perf.h"
00018
00019
00020
00021 static const float s_radiansPerDegree = M_PI / 180.0;
00022
00023
00024
00025 struct axis_t {
00026
00027 axis_t(void) throw() { this->clear(); }
00028 void clear(void) throw() {
00029 windAngle.clear();
00030 windStep.clear();
00031 run = 0;
00032 }
00033
00034
00035 point3d_t windAngle;
00036 point3d_t windStep;
00037 int run;
00038 };
00039
00040
00041 typedef std::map<std::string, smart_ptr<axis_t> > axis_map_t;
00042
00043
00044
00045 struct state_t {
00046
00047 axis_t * getAxis(IN const char * name) {
00048 ASSERT(name, "null");
00049 axis_map_t::iterator i = axisMap.find(name);
00050 ASSERT_THROW(axisMap.end() != i,
00051 "No such axis: '" << name << "'");
00052 ASSERT(i->second, "null axis in map?");
00053 return i->second;
00054 }
00055
00056
00057 axis_map_t axisMap;
00058 };
00059
00060
00061
00063
00064
00065
00067
00068 static smart_ptr<axis_t>
00069 parseAxis
00070 (
00071 IN const Datahash * hash
00072 )
00073 {
00074 smart_ptr<axis_t> axis = new axis_t;
00075 ASSERT(axis, "out of memory");
00076
00077 axis->run = getInt(hash, "run");
00078
00079
00080 smart_ptr<Datahash> wind = getSubhash(hash, "winding");
00081 ASSERT(wind, "null");
00082
00083 const char * rot = getOptionalString(wind, "rot", "");
00084 const char * step = getOptionalString(wind, "step", "");
00085
00086 point3d_t rotateDegrees;
00087 parsePoint3d(rot, rotateDegrees);
00088 axis->windAngle = s_radiansPerDegree * rotateDegrees;
00089 parsePoint3d(step, axis->windStep);
00090
00091 return axis;
00092 }
00093
00094
00095
00096 static void
00097 getAxisRegistry
00098 (
00099 IN axis_map_t& map,
00100 IN const Datahash * input
00101 )
00102 {
00103 ASSERT(input, "null");
00104 map.clear();
00105
00106 Datahash::iterator_t i;
00107 input->getIterator("axis", i);
00108 while (const hash_value_t * phv = input->getNextElementUnsafe(i)) {
00109 if (!phv->hash)
00110 continue;
00111
00112 smart_ptr<axis_t> axis = parseAxis(phv->hash);
00113 if (axis) {
00114 const char * name = getString(phv->hash, "name");
00115 ASSERT_THROW(map.end() == map.find(name),
00116 "Multiple axes with same name: '" << name << "'");
00117 map[name] = axis;
00118 }
00119 }
00120 DPRINTF("Parsed %d axes", map.size());
00121 }
00122
00123
00124
00125 static void
00126 updateTransformation
00127 (
00128 IN const matrix4_t& rootT,
00129 IN const axis_t * axis,
00130 OUT matrix4_t& T
00131 )
00132 {
00133 ASSERT(axis, "null");
00134
00135
00136 matrix4_t rot;
00137 rot.setYRotation(axis->windAngle.y);
00138
00139
00140 matrix4_t trans;
00141 trans.setTranslation(axis->windStep);
00142
00143 matrix4_t next;
00144 next.setToProductOf(rot, trans);
00145
00146 T.setToProductOf(rootT, next);
00147 }
00148
00149
00150
00151 static void
00152 generateRooms
00153 (
00154 IN state_t& state,
00155 IN const matrix4_t& rootT,
00156 IN const axis_t * axis,
00157 IN int count
00158 )
00159 {
00160 ASSERT(axis, "null");
00161 ASSERT(axis->run >= 0, "bad run?");
00162 ASSERT(count >= 0, "invalid room count: %d", count);
00163
00164
00165 if (count >= axis->run)
00166 return;
00167
00168
00169 matrix4_t T;
00170 updateTransformation(rootT, axis, T);
00171
00172
00173 point3d_t p(0, 0, 0);
00174 point3d_t q = T * p;
00175
00176 DPRINTF("Room %d:", count);
00177 q.dump(" position");
00178
00179
00180 generateRooms(state, T, axis, count + 1);
00181 }
00182
00183
00184
00185 static void
00186 genBuilding
00187 (
00188 IN const Datahash * input
00189 )
00190 {
00191 ASSERT(input, "null");
00192
00193 state_t state;
00194
00195
00196 getAxisRegistry(state.axisMap, input);
00197
00198
00199 const char * rootName = getString(input, "rootAxis");
00200 DPRINTF("Root axis name: '%s'", rootName);
00201
00202 axis_t * axis = state.getAxis(rootName);
00203 ASSERT(axis, "null root axis");
00204
00205
00206 matrix4_t T;
00207 T.setIdentity();
00208 {
00209 perf::Timer timer("room-generation");
00210 generateRooms(state, T, axis, 0);
00211 }
00212 }
00213
00214
00215
00217
00218
00219
00221
00222 int
00223 main
00224 (
00225 IN int argc,
00226 IN const char * argv[]
00227 )
00228 {
00229 int retval = 0;
00230 ASSERT(2 == argc,
00231 "usage: genBuilding <input-file>");
00232 const char * infile = argv[1];
00233 DPRINTF("Using input file: '%s'", infile);
00234
00235 try {
00236 perf::Timer timer("overall timer");
00237
00238 smart_ptr<Datahash> input = readHashFromTextFile(infile);
00239 ASSERT(input, "null");
00240
00241 genBuilding(input);
00242
00243 } catch (std::exception& e) {
00244 retval = 1;
00245 DPRINTF("Exception: %s", e.what());
00246 }
00247
00248 perf::dumpTimingSummary(std::cerr);
00249
00250 return retval;
00251 }
00252