00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_VISX_HOUSE_CC_UTC20050626084015_DEFINED
00035 #define GROOVX_VISX_HOUSE_CC_UTC20050626084015_DEFINED
00036
00037 #include "house.h"
00038
00039 #include "geom/rect.h"
00040 #include "geom/vec3.h"
00041
00042 #include "gfx/bbox.h"
00043 #include "gfx/canvas.h"
00044
00045 #include "io/ioproxy.h"
00046 #include "io/reader.h"
00047 #include "io/writer.h"
00048
00049 #include "rutz/algo.h"
00050
00051 #include "rutz/trace.h"
00052 #include "rutz/debug.h"
00053 GVX_DBG_REGISTER
00054
00055 using geom::rectd;
00056 using geom::vec2d;
00057 using geom::vec3d;
00058
00060
00061
00062
00064
00065 namespace
00066 {
00067 const io::version_id HOUSE_SVID = 3;
00068
00069 void drawWindow(Gfx::Canvas& canvas, int num_vert_bars, int num_horiz_bars)
00070 {
00071 GVX_TRACE("House::drawWindow");
00072
00073
00074 {
00075 Gfx::LinesBlock block(canvas, "window bars");
00076
00077 for (int x = 1; x < (num_vert_bars+1); ++x)
00078 {
00079 double xpos = double(x)/(num_vert_bars+1) - 0.5;
00080 canvas.vertex2(vec2d(xpos, -0.5));
00081 canvas.vertex2(vec2d(xpos, 0.5));
00082 }
00083 for (int y = 1; y < (num_horiz_bars+1); ++y)
00084 {
00085 double ypos = double(y)/(num_horiz_bars+1) - 0.5;
00086 canvas.vertex2(vec2d(-0.5, ypos));
00087 canvas.vertex2(vec2d( 0.5, ypos));
00088 }
00089 }
00090
00091 {
00092 Gfx::QuadsBlock block(canvas, "window outline");
00093 canvas.vertex2(vec2d(-0.5, -0.5));
00094 canvas.vertex2(vec2d( 0.5, -0.5));
00095 canvas.vertex2(vec2d( 0.5, 0.5));
00096 canvas.vertex2(vec2d(-0.5, 0.5));
00097 }
00098 }
00099
00100 void drawDoor(Gfx::Canvas& canvas)
00101 {
00102 GVX_TRACE("House::drawDoor");
00103
00104 canvas.drawRect(rectd::lbwh(-0.5, 0.0, 1.0, 1.0));
00105
00106 Gfx::LinesBlock block(canvas, "door");
00107
00108 canvas.vertex2(vec2d(0.25, 0.35));
00109 canvas.vertex2(vec2d(0.25, 0.45));
00110 }
00111
00112 void drawStoryFrame(Gfx::Canvas& canvas)
00113 {
00114 GVX_TRACE("House::drawStoryFrame");
00115
00116 canvas.drawRect(rectd::lbwh(-0.5, -0.5, 1.0, 1.0));
00117 }
00118
00119 void drawTriangleRoof(Gfx::Canvas& canvas)
00120 {
00121 GVX_TRACE("House::drawTriangleRoof");
00122
00123
00124 {
00125 Gfx::TrianglesBlock block(canvas, "triangle roof");
00126 canvas.vertex2(vec2d(-0.5, 0.0));
00127 canvas.vertex2(vec2d( 0.5, 0.0));
00128 canvas.vertex2(vec2d( 0.0, 1.0));
00129 }
00130 {
00131 Gfx::LinesBlock block(canvas, "triangle roof ledge");
00132 canvas.vertex2(vec2d(-0.5, 0.0));
00133 canvas.vertex2(vec2d( 0.5, 0.0));
00134 }
00135 }
00136
00137 void drawTrapezoidRoof(Gfx::Canvas& canvas)
00138 {
00139 GVX_TRACE("House::drawTrapezoidRoof");
00140 {
00141 Gfx::QuadsBlock block(canvas, "trapezoid roof");
00142 canvas.vertex2(vec2d(-0.5, 0.0));
00143 canvas.vertex2(vec2d( 0.5, 0.0));
00144 canvas.vertex2(vec2d( 0.4, 1.0));
00145 canvas.vertex2(vec2d(-0.4, 1.0));
00146 }
00147 {
00148 Gfx::LinesBlock block(canvas, "trapezoid roof overhand");
00149 canvas.vertex2(vec2d(-0.5, 0.0));
00150 canvas.vertex2(vec2d( 0.5, 0.0));
00151 }
00152 }
00153
00154 void drawSquareRoof(Gfx::Canvas& canvas)
00155 {
00156 GVX_TRACE("House::drawSquareRoof");
00157 {
00158 Gfx::QuadsBlock block(canvas, "square roof");
00159 canvas.vertex2(vec2d(-0.5, 0.0));
00160 canvas.vertex2(vec2d( 0.5, 0.0));
00161 canvas.vertex2(vec2d( 0.5, 1.0));
00162 canvas.vertex2(vec2d(-0.5, 1.0));
00163 }
00164 {
00165 Gfx::LinesBlock block(canvas, "square roof overhang");
00166 canvas.vertex2(vec2d(-0.5, 0.0));
00167 canvas.vertex2(vec2d( 0.5, 0.0));
00168 }
00169 }
00170
00171 void drawChimney(Gfx::Canvas& canvas)
00172 {
00173 GVX_TRACE("House::drawChimney");
00174 {
00175 Gfx::QuadsBlock block(canvas, "chimney");
00176 canvas.vertex2(vec2d( 0.5, 0.0));
00177 canvas.vertex2(vec2d(-0.5, 0.0));
00178 canvas.vertex2(vec2d(-0.5, 1.0));
00179 canvas.vertex2(vec2d( 0.5, 1.0));
00180 }
00181 }
00182 }
00183
00185
00186
00187
00189
00190 const FieldMap& House::classFields()
00191 {
00192 static const Field FIELD_ARRAY[] =
00193 {
00194 Field("storyAspectRatio",
00195 &House::itsStoryAspectRatio, 3.0, 0.5, 10.0, 0.05, Field::NEW_GROUP),
00196 Field("numStories", &House::itsNumStories, 2, 1, 5, 1),
00197
00198 Field("doorPosition", &House::itsDoorPosition, 2, 0, 5, 1, Field::NEW_GROUP),
00199 Field("doorWidth", &House::itsDoorWidth, 0.75, 0.05, 1.0, 0.05),
00200 Field("doorHeight", &House::itsDoorHeight, 0.75, 0.05, 1.0, 0.05),
00201 Field("doorOrientation",
00202 &House::itsDoorOrientation, false, false, true, true),
00203
00204 Field("numWindows", &House::itsNumWindows, 5, 2, 6, 1, Field::NEW_GROUP),
00205 Field("windowWidth", &House::itsWindowWidth, 0.75, 0.05, 1.0, 0.05),
00206 Field("windowHeight", &House::itsWindowHeight, 0.5, 0.05, 1.0, 0.05),
00207 Field("windowVertBars", &House::itsWindowVertBars, 1, 0, 5, 1),
00208 Field("windowHorizBars", &House::itsWindowHorizBars, 1, 0, 5, 1),
00209
00210 Field("roofShape", &House::itsRoofShape, 0, 0, 2, 1, Field::NEW_GROUP),
00211 Field("roofHeight", &House::itsRoofHeight, 0.05, 0.05, 2.0, 0.05),
00212 Field("roofOverhang", &House::itsRoofOverhang, 0.75, 0.0, 0.5, 0.05),
00213 Field("roofColor", &House::itsRoofColor, 1, 0, 1, 1),
00214
00215 Field("chimneyXPosition",
00216 &House::itsChimneyXPosition, 0.2, -0.5, 0.5, 0.05, Field::NEW_GROUP),
00217 Field("chimneyYPosition",
00218 &House::itsChimneyYPosition, 0.5, 0.0, 1.0, 0.05),
00219 Field("chimneyWidth", &House::itsChimneyWidth, 0.06, 0.01, 0.30, 0.01),
00220 Field("chimneyHeight", &House::itsChimneyHeight, 0.5, 0.05, 2.0, 0.1)
00221 };
00222
00223 static FieldMap HOUSE_FIELDS(FIELD_ARRAY, &GxShapeKit::classFields());
00224
00225 return HOUSE_FIELDS;
00226 }
00227
00228 House* House::make()
00229 {
00230 GVX_TRACE("House::make");
00231 return new House;
00232 }
00233
00234 House::House() :
00235 itsStoryAspectRatio(3.0),
00236 itsNumStories(2),
00237
00238 itsDoorPosition(2),
00239 itsDoorWidth(0.75),
00240 itsDoorHeight(0.75),
00241 itsDoorOrientation(false),
00242
00243 itsNumWindows(5),
00244 itsWindowWidth(0.75),
00245 itsWindowHeight(0.5),
00246 itsWindowVertBars(1),
00247 itsWindowHorizBars(1),
00248
00249 itsRoofShape(0),
00250 itsRoofOverhang(0.05),
00251 itsRoofHeight(0.75),
00252 itsRoofColor(1),
00253
00254 itsChimneyXPosition(0.2),
00255 itsChimneyYPosition(0.5),
00256 itsChimneyWidth(0.06),
00257 itsChimneyHeight(0.5)
00258 {
00259 GVX_TRACE("House::House");
00260
00261 setFieldMap(House::classFields());
00262 }
00263
00264 House::~House() throw()
00265 {
00266 GVX_TRACE("House::~House");
00267 }
00268
00269 io::version_id House::class_version_id() const
00270 {
00271 GVX_TRACE("House::class_version_id");
00272 return HOUSE_SVID;
00273 }
00274
00275 void House::read_from(io::reader& reader)
00276 {
00277 GVX_TRACE("House::read_from");
00278
00279 reader.ensure_version_id("House", 3,
00280 "Try cvs tag xml_conversion_20040526",
00281 SRC_POS);
00282
00283 readFieldsFrom(reader, classFields());
00284
00285 reader.read_base_class("GxShapeKit", io::make_proxy<GxShapeKit>(this));
00286 }
00287
00288 void House::write_to(io::writer& writer) const
00289 {
00290 GVX_TRACE("House::write_to");
00291
00292 writer.ensure_output_version_id("House", HOUSE_SVID, 3,
00293 "Try groovx0.8a4", SRC_POS);
00294
00295 writeFieldsTo(writer, classFields(), HOUSE_SVID);
00296
00297 writer.write_base_class("GxShapeKit", io::make_const_proxy<GxShapeKit>(this));
00298 }
00299
00301
00302
00303
00305
00306 void House::grGetBoundingBox(Gfx::Bbox& bbox) const
00307 {
00308 GVX_TRACE("House::grGetBoundingBox");
00309
00310 const double main_width = itsStoryAspectRatio;
00311 const double main_height = itsNumStories + itsRoofHeight;
00312
00313 using rutz::max;
00314
00315 const double max_dim = max(main_height, main_width);
00316
00317 const double extra_chimney_height =
00318 max(0.0, itsChimneyYPosition + itsChimneyHeight - itsRoofHeight);
00319
00320 const double l = -main_width/2.0 * (1 + max(itsRoofOverhang, 0.0)) / max_dim;
00321 const double r = main_width/2.0 * (1 + max(itsRoofOverhang, 0.0)) / max_dim;
00322 const double b = -main_height/2.0 / max_dim;
00323 const double t = (main_height/2.0 + extra_chimney_height) / max_dim;
00324
00325 bbox.drawRect(rectd::ltrb(l,t,r,b));
00326 }
00327
00328 void House::grRender(Gfx::Canvas& canvas) const
00329 {
00330 GVX_TRACE("House::grRender");
00331 const double total_width = itsStoryAspectRatio;
00332 const double total_height = itsNumStories + itsRoofHeight;
00333
00334 const double max_dimension =
00335 (total_height > total_width) ? total_height : total_width;
00336
00337 Gfx::MatrixSaver msaver(canvas, "house");
00338 Gfx::AttribSaver asaver(canvas);
00339
00340
00341
00342
00343 canvas.scale(vec3d(itsStoryAspectRatio/max_dimension,
00344 1.0/max_dimension, 1.0));
00345
00346
00347
00348
00349 canvas.translate(vec3d(0.0, -total_height/2.0 + 0.5, 0.0));
00350
00351 canvas.setPolygonFill(false);
00352
00353
00354
00355 for (int s = 0; s < itsNumStories; ++s)
00356 {
00357 drawStoryFrame(canvas);
00358
00359
00360 for (int w = 0; w < itsNumWindows; ++w)
00361 {
00362 Gfx::MatrixSaver msaver(canvas, "window");
00363
00364 double x_pos = double(w+0.5)/itsNumWindows - 0.5;
00365 if (s == 0 && w == itsDoorPosition )
00366 {
00367
00368 canvas.translate(vec3d(x_pos, -0.5, 0.0));
00369 canvas.scale(vec3d(itsDoorWidth/itsNumWindows,
00370 itsDoorHeight, 1.0));
00371 if (itsDoorOrientation)
00372 {
00373 canvas.scale(vec3d(-1.0, 1.0, 1.0));
00374 }
00375 drawDoor(canvas);
00376 }
00377 else
00378 {
00379
00380 canvas.translate(vec3d(x_pos, 0.0, 0.0));
00381 canvas.scale(vec3d(itsWindowWidth/itsNumWindows,
00382 itsWindowHeight, 1.0));
00383 drawWindow(canvas, itsWindowVertBars, itsWindowHorizBars);
00384 }
00385 }
00386
00387 canvas.translate(vec3d(0.0, 1.0, 0.0));
00388 }
00389
00390
00391
00392 canvas.translate(vec3d(0.0, -0.5, 0.0));
00393
00394 {
00395 Gfx::MatrixSaver msaver(canvas, "roof");
00396 Gfx::AttribSaver asaver(canvas);
00397
00398 canvas.scale(vec3d(1.0+itsRoofOverhang, itsRoofHeight, 1.0));
00399
00400 canvas.setPolygonFill((itsRoofColor == 0));
00401
00402 if (itsRoofShape == 0)
00403 {
00404 drawTriangleRoof(canvas);
00405 }
00406 else if (itsRoofShape == 1)
00407 {
00408 drawTrapezoidRoof(canvas);
00409 }
00410 else
00411 {
00412 drawSquareRoof(canvas);
00413 }
00414 }
00415
00416
00417 {
00418 Gfx::MatrixSaver msaver(canvas, "chimney");
00419 Gfx::AttribSaver asaver(canvas);
00420
00421 canvas.translate(vec3d(itsChimneyXPosition,
00422 itsChimneyYPosition, 0.0));
00423 canvas.scale(vec3d(itsChimneyWidth,
00424 itsChimneyHeight, 1.0));
00425
00426 canvas.setPolygonFill(true);
00427 drawChimney(canvas);
00428 }
00429 }
00430
00431 static const char __attribute__((used)) vcid_groovx_visx_house_cc_utc20050626084015[] = "$Id: house.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00432 #endif // !GROOVX_VISX_HOUSE_CC_UTC20050626084015_DEFINED