00001
00002
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 #include "Scene.h"
00028 #include "DisplayDevice.h"
00029 #include "Inform.h"
00030 #include "DispCmds.h"
00031 #include "utilities.h"
00032 #include "FileRenderList.h"
00033 #include "FileRenderer.h"
00034
00035 static const int num_scalemethods = 12;
00036 static const ColorScale defScales[] = {
00037 { {1.0, 0.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, "RWB"},
00038 { {0.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, "BWR"},
00039 { {1.0, 0.0, 0.0}, {0.5, 0.5, 0.5}, {0.0, 0.0, 1.0}, "RGryB"},
00040 { {0.0, 0.0, 1.0}, {0.5, 0.5, 0.5}, {1.0, 0.0, 0.0}, "BGryR"},
00041 { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, "RGB"},
00042 { {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, "BGR"},
00043 { {1.0, 0.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, "RWG"},
00044 { {0.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, "GWR"},
00045 { {0.0, 1.0, 0.0}, {1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, "GWB"},
00046 { {0.0, 0.0, 1.0}, {1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, "BWG"},
00047 { {0.0, 0.0, 0.0}, {0.5, 0.5, 0.5}, {1.0, 1.0, 1.0}, "BlkW"},
00048 { {1.0, 1.0, 1.0}, {0.5, 0.5, 0.5}, {0.0, 0.0, 0.0}, "WBlk"}
00049 };
00050
00051
00052
00053
00054 static const char *defColorNames[REGCLRS] = {
00055 "blue", "red", "gray", "orange",
00056 "yellow", "tan", "silver", "green",
00057 "white", "pink", "cyan", "purple",
00058 "lime", "mauve", "ochre", "iceblue",
00059
00060
00061 "black"
00062
00063 #if (REGCLRS > 17)
00064 ,"yellow2", "yellow3", "green2", "green3",
00065 "cyan2", "cyan3", "blue2", "blue3",
00066 "violet", "violet2", "magenta", "magenta2",
00067 "red2", "red3", "orange2", "orange3"
00068 #endif
00069
00070 };
00071
00072 const float Scene::defaultColor[] = {
00073 0.0f, 0.0f, 1.00f, 1.0f, 0.0f, 0.0f,
00074 0.35f, 0.35f, 0.35f, 1.0f, 0.5f, 0.0f,
00075 1.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.2f,
00076 0.6f, 0.6f, 0.6f, 0.0f, 1.0f, 0.0f,
00077 1.0f, 1.0f, 1.0f, 1.0f, 0.6f, 0.6f,
00078 0.25f, 0.75f, 0.75f, 0.65f, 0.0f, 0.65f,
00079 0.5f, 0.9f, 0.4f, 0.9f, 0.4f, 0.7f,
00080 0.5f, 0.3f, 0.0f, 0.5f, 0.5f, 0.75f,
00081
00082
00083 0.0f, 0.0f, 0.0f
00084
00085 #if (REGCLRS > 17)
00086 ,0.88f, 0.97f, 0.02f, 0.55f, 0.90f, 0.02f,
00087 0.00f, 0.90f, 0.04f, 0.00f, 0.90f, 0.50f,
00088 0.00f, 0.88f, 1.00f, 0.00f, 0.76f, 1.00f,
00089 0.02f, 0.38f, 0.67f, 0.01f, 0.04f, 0.93f,
00090 0.27f, 0.00f, 0.98f, 0.45f, 0.00f, 0.90f,
00091 0.90f, 0.00f, 0.90f, 1.00f, 0.00f, 0.66f,
00092 0.98f, 0.00f, 0.23f, 0.81f, 0.00f, 0.00f,
00093 0.89f, 0.35f, 0.00f, 0.96f, 0.72f, 0.00f
00094 #endif
00095
00096 };
00097
00098
00100 class DisplayColor : public Displayable {
00101 private:
00102 int colorCat;
00103 int dcindex;
00104 int dccolor;
00105 int changed;
00106
00107 protected:
00108 void do_color_changed(int cat) {
00109 if (cat == colorCat) {
00110 dccolor = scene->category_item_value(colorCat, dcindex);
00111 changed = 1;
00112 }
00113 }
00114 void do_color_rgb_changed(int color) {
00115 if (color == dccolor)
00116 changed = 1;
00117 }
00118
00119 public:
00120 DisplayColor(Displayable *d, const char *coloritemname, int colorindex)
00121 : Displayable(d), changed(0) {
00122
00123 colorCat = scene->category_index("Display");
00124 if (colorCat == -1) {
00125 colorCat = scene->add_color_category("Display");
00126 }
00127 dcindex = scene->add_color_item(colorCat, coloritemname, colorindex);
00128 do_color_changed(colorCat);
00129 }
00130 int color_changed() const { return changed; }
00131 void clear_changed() { changed = 0; }
00132 int color_id() const { return dccolor; }
00133 };
00134
00135
00137 Scene::Scene() : root(this) {
00138 set_background_mode(0);
00139 reset_lights();
00140
00141
00142 int i;
00143 for (i=BEGREGCLRS; i<REGCLRS; i++) {
00144 colorNames.add_name(defColorNames[i], i);
00145 set_color_value(i, defaultColor + 3*i);
00146 }
00147
00148 for (i=0; i<num_scalemethods; i++)
00149 colorScales.append(defScales[i]);
00150 scaleMethod = 0;
00151 scaleMin = 0.1f;
00152 scaleMax = 1.0f;
00153 scaleMid = 0.5f;
00154 create_colorscale();
00155
00156
00157 background = new DisplayColor(&root, "Background", REGBLACK);
00158 background_color_changed = 0;
00159 background_color_id = 0;
00160
00161
00162 backgradtop = new DisplayColor(&root, "BackgroundTop", REGBLACK);
00163 backgradtop_color_changed = 0;
00164 backgradtop_color_id = 0;
00165 backgradbot = new DisplayColor(&root, "BackgroundBot", REGBLUE2);
00166 backgradbot_color_changed = 0;
00167 backgradbot_color_id = 0;
00168
00169
00170 foreground = new DisplayColor(&root, "Foreground", REGWHITE);
00171 foreground_color_changed = 0;
00172 foreground_color_id = 0;
00173 }
00174
00176 Scene::~Scene(void) {
00177 for (int i=0; i<categories.num(); i++) delete categories.data(i);
00178 }
00179
00181
00182
00183 void Scene::set_background_mode(int mode) {
00184 backgroundmode = mode;
00185 backgroundmode_changed = 1;
00186 }
00187
00188
00189 int Scene::background_mode(void) {
00190 return backgroundmode;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 static const float def_light_color[3] = { 1.0, 1.0, 1.0 };
00200 static const float def_light_pos[DISP_LIGHTS][3] = {
00201 { -0.1f, 0.1f, 1.0f }, { 1.0f, 2.0f, 0.5f },
00202 { -1.0f, 2.0f, -1.0f }, { -1.0f, -1.0f, 0.0f }
00203 };
00204 static const float def_adv_light_pos[DISP_LIGHTS][3] = {
00205 { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f },
00206 { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }
00207 };
00208
00209 static const int def_light_on[DISP_LIGHTS] = { TRUE, TRUE, FALSE, FALSE };
00210
00211 void Scene::define_light(int n, const float *color, const float *position) {
00212 if (n < 0 || n >= DISP_LIGHTS)
00213 return;
00214
00215 for (int i=0; i < 3; i++) {
00216 lightState[n].color[i] = color[i];
00217 lightState[n].pos[i] = position[i];
00218 }
00219 light_changed = 1;
00220 }
00221
00222 void Scene::activate_light(int n, int turnon) {
00223 if (n < 0 || n >= DISP_LIGHTS )
00224 return;
00225 lightState[n].on = turnon;
00226 light_changed = 1;
00227 }
00228
00229 void Scene::rotate_light(int n, float theta, char axis) {
00230 if (n < 0 || n >= DISP_LIGHTS)
00231 return;
00232 Matrix4 mat;
00233 mat.rot(theta,axis);
00234 mat.multpoint3d(lightState[n].pos,lightState[n].pos);
00235 light_changed = 1;
00236 }
00237
00238 void Scene::move_light(int n, const float *p) {
00239 if (n < 0 || n >= DISP_LIGHTS) return;
00240 for (int i=0; i<3; i++) lightState[n].pos[i] = p[i];
00241 light_changed = 1;
00242 }
00243
00244 const float *Scene::light_pos(int n) const {
00245 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00246 return lightState[n].pos;
00247 }
00248
00249 const float *Scene::light_pos_default(int n) const {
00250 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00251 return def_light_pos[n];
00252 }
00253
00254 const float *Scene::light_color(int n) const {
00255 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00256 return lightState[n].color;
00257 }
00258
00259 const float *Scene::light_color_default(int n) const {
00260 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00261 return def_light_color;
00262 }
00263
00264
00265 void Scene::define_adv_light(int n, const float *color,
00266 const float *position,
00267 float constant, float linear, float quad,
00268 float *spotdir,
00269 float fallstart, float fallend, int spoton) {
00270 if (n < 0 || n >= DISP_LIGHTS)
00271 return;
00272
00273 for (int i=0; i < 3; i++) {
00274 advLightState[n].color[i] = color[i];
00275 advLightState[n].pos[i] = position[i];
00276 advLightState[n].spotdir[i] = spotdir[i];
00277 }
00278 advLightState[n].constfactor = constant;
00279 advLightState[n].linearfactor = linear;
00280 advLightState[n].quadfactor = quad;
00281 advLightState[n].fallstart = fallstart;
00282 advLightState[n].fallend = fallend;
00283 advLightState[n].spoton = spoton;
00284 adv_light_changed = 1;
00285 }
00286
00287 void Scene::activate_adv_light(int n, int turnon) {
00288 if (n < 0 || n >= DISP_LIGHTS )
00289 return;
00290 advLightState[n].on = turnon;
00291 adv_light_changed = 1;
00292 }
00293
00294 void Scene::move_adv_light(int n, const float *p) {
00295 if (n < 0 || n >= DISP_LIGHTS) return;
00296 for (int i=0; i<3; i++)
00297 advLightState[n].pos[i] = p[i];
00298 adv_light_changed = 1;
00299 }
00300
00301 const float *Scene::adv_light_pos(int n) const {
00302 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00303 return advLightState[n].pos;
00304 }
00305
00306 const float *Scene::adv_light_pos_default(int n) const {
00307 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00308 return def_adv_light_pos[n];
00309 }
00310
00311 const float *Scene::adv_light_color(int n) const {
00312 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00313 return advLightState[n].color;
00314 }
00315
00316 const float *Scene::adv_light_color_default(int n) const {
00317 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00318 return def_light_color;
00319 }
00320
00321 void Scene::adv_light_attenuation(int n, float constant, float linear,
00322 float quad) {
00323 if (n < 0 || n >= DISP_LIGHTS) return;
00324 advLightState[n].constfactor = constant;
00325 advLightState[n].linearfactor = linear;
00326 advLightState[n].quadfactor = quad;
00327 }
00328
00329 void Scene::adv_light_get_attenuation(int n, float &constant, float &linear,
00330 float &quad) const {
00331 if (n < 0 || n >= DISP_LIGHTS) return;
00332 constant = advLightState[n].constfactor;
00333 linear = advLightState[n].linearfactor;
00334 quad = advLightState[n].quadfactor;
00335 }
00336
00337 void Scene::adv_light_spotlight(int n, float *spotdir, float fallstart,
00338 float fallend, int spoton) {
00339 if (n < 0 || n >= DISP_LIGHTS) return;
00340 advLightState[n].fallstart = fallstart;
00341 advLightState[n].fallend = fallend;
00342 advLightState[n].spoton = spoton;
00343 for (int i=0; i<3; i++)
00344 advLightState[n].spotdir[i] = spotdir[i];
00345 }
00346
00347 const float *Scene::adv_light_get_spotlight(int n, float &fallstart,
00348 float &fallend, int &spoton) const {
00349 if (n < 0 || n >= DISP_LIGHTS) return NULL;
00350 fallstart = advLightState[n].fallstart;
00351 fallend = advLightState[n].fallend;
00352 spoton = advLightState[n].spoton;
00353 return advLightState[n].spotdir;
00354 }
00355
00356 void Scene::reset_lights(void) {
00357 int i;
00358
00359
00360 for (i=0; i<DISP_LIGHTS; i++) {
00361 define_light(i, def_light_color, def_light_pos[i]);
00362 activate_light(i, def_light_on[i]);
00363 }
00364 light_changed = 1;
00365
00366
00367 for (i=0; i<DISP_LIGHTS; i++) {
00368 float spotdir[] = { 0.0f, 0.0f, 1.0f };
00369 define_adv_light(i, def_light_color, def_light_pos[i],
00370 1.0f, 0.0f, 0.0f,
00371 spotdir, 0.3f, 0.7f, 0);
00372 activate_adv_light(i, 0);
00373 }
00374 adv_light_changed = 1;
00375 }
00376
00377
00378
00379 int Scene::prepare() {
00380 background_color_changed = background->color_changed();
00381 background_color_id = background->color_id();
00382 background->clear_changed();
00383
00384 backgradtop_color_changed = backgradtop->color_changed();
00385 backgradtop_color_id = backgradtop->color_id();
00386 backgradtop->clear_changed();
00387
00388 backgradbot_color_changed = backgradbot->color_changed();
00389 backgradbot_color_id = backgradbot->color_id();
00390 backgradbot->clear_changed();
00391
00392 foreground_color_changed = foreground->color_changed();
00393 foreground_color_id = foreground->color_id();
00394 foreground->clear_changed();
00395
00396 return root.draw_prepare() || backgroundmode_changed || light_changed ||
00397 background_color_changed ||
00398 backgradtop_color_changed || backgradbot_color_changed ||
00399 foreground_color_changed;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 void Scene::draw(DisplayDevice *display) {
00419 if (!display)
00420 return;
00421
00422 if (!display->is_renderer_process())
00423 return;
00424
00425
00426 if (backgroundmode_changed) {
00427 display->set_background_mode(backgroundmode);
00428 }
00429
00430
00431
00432 if (light_changed) {
00433
00434 for (int i=0; i<DISP_LIGHTS; i++) {
00435 display->do_define_light(i, lightState[i].color, lightState[i].pos);
00436 display->do_activate_light(i, lightState[i].on);
00437 }
00438 }
00439
00440 #if 0
00441
00442
00443
00444 if (adv_light_changed) {
00445
00446 for (int i=0; i<DISP_LIGHTS; i++) {
00447 display->do_define_light(i, lightState[i].color, lightState[i].pos);
00448 display->do_activate_light(i, lightState[i].on);
00449 }
00450 }
00451 #endif
00452
00453
00454 display->use_colors(colorData);
00455
00456
00457
00458
00459
00460
00461
00462 if (background_color_changed) {
00463 display->set_background(color_value(background_color_id));
00464 }
00465
00466
00467
00468 if (backgradtop_color_changed || backgradbot_color_changed) {
00469 display->set_backgradient(color_value(backgradtop->color_id()),
00470 color_value(backgradbot->color_id()));
00471 }
00472
00473
00474 display->prepare3D(TRUE);
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 if (display->forced_stereo_draws() && !(display->stereo_mode())) {
00487 display->left();
00488
00489 display->prepareOpaque();
00490 root.draw(display);
00491 if (display->prepareTrans()) {
00492 root.draw(display);
00493 }
00494
00495 display->right();
00496
00497 display->prepareOpaque();
00498 root.draw(display);
00499 if (display->prepareTrans()) {
00500 root.draw(display);
00501 }
00502 } else {
00503
00504 if (display->stereo_mode())
00505 display->left();
00506 else
00507 display->normal();
00508
00509
00510 display->prepareOpaque();
00511 root.draw(display);
00512
00513 if (display->prepareTrans()) {
00514 root.draw(display);
00515 }
00516
00517
00518 if (display->stereo_mode()) {
00519 display->right();
00520 display->prepareOpaque();
00521 root.draw(display);
00522
00523 if (display->prepareTrans()) {
00524 root.draw(display);
00525 }
00526 }
00527 }
00528
00529 display->render_done();
00530
00531
00532 display->update(TRUE);
00533 }
00534
00535
00536
00537
00538 int Scene::filedraw(FileRenderer *render, const char *filename,
00539 DisplayDevice *display) {
00540 int i;
00541
00542
00543 (*((DisplayDevice *)render)) = (*display);
00544
00545
00546 for (i=0; i<DISP_LIGHTS; i++) {
00547 if (lightState[i].on)
00548 render->do_define_light(i, lightState[i].color, lightState[i].pos);
00549 render->do_activate_light(i, lightState[i].on);
00550 }
00551
00552
00553 for (i=0; i<DISP_LIGHTS; i++) {
00554 if (advLightState[i].on)
00555 render->do_define_adv_light(i,
00556 advLightState[i].color,
00557 advLightState[i].pos,
00558 advLightState[i].constfactor,
00559 advLightState[i].linearfactor,
00560 advLightState[i].quadfactor,
00561 advLightState[i].spotdir,
00562 advLightState[i].fallstart,
00563 advLightState[i].fallend,
00564 advLightState[i].spoton);
00565 render->do_activate_adv_light(i, advLightState[i].on);
00566 }
00567
00568
00569 render->use_colors(colorData);
00570 render->set_background(color_value(background->color_id()));
00571 render->set_backgradient(color_value(backgradtop->color_id()),
00572 color_value(backgradbot->color_id()));
00573
00574
00575 if (!render->open_file(filename)) {
00576 return FALSE;
00577 }
00578
00579 render->prepare3D(TRUE);
00580
00581
00582 root.draw(render);
00583
00584
00585 render->render_done();
00586 render->update(TRUE);
00587
00588
00589 return TRUE;
00590 }
00591
00592
00593
00594 void Scene::draw_finished() {
00595
00596 backgroundmode_changed=0;
00597 light_changed = 0;
00598 adv_light_changed = 0;
00599 }
00600
00601
00602
00604
00605
00606 static float slope3_lower(float mid, float val) {
00607 if (val > mid) return 0.0f;
00608 if (mid == 0) return 1.0f;
00609 return (1.0f - val / mid);
00610 }
00611
00612
00613 static float slope3_upper(float mid, float val) {
00614 if (val < mid) return 0.0f;
00615 if (mid == 1) return 1.0f;
00616 return (1.0f - (1.0f - val) / (1.0f - mid));
00617 }
00618
00619
00620 static float slope3_middle(float mid, float val) {
00621 if (val < mid) {
00622 return val / mid;
00623 }
00624 if (val > mid) {
00625 return (1-val) / (1-mid);
00626 }
00627 return 1.0;
00628 }
00629
00630
00631
00632 static void scale_color(const float *lowRGB, const float *midRGB,
00633 const float *highRGB,
00634 float mid, float val, float scaleMin, float *rgb) {
00635 float w1 = slope3_lower(mid, val);
00636 float w2 = slope3_middle(mid, val);
00637 float w3 = slope3_upper(mid, val);
00638 float wsum = (w1 + w2 + w3);
00639
00640 rgb[0] = (lowRGB[0]*w1 + midRGB[0]*w2 + highRGB[0]*w3) / wsum + scaleMin;
00641 rgb[1] = (lowRGB[1]*w1 + midRGB[1]*w2 + highRGB[1]*w3) / wsum + scaleMin;
00642 rgb[2] = (lowRGB[2]*w1 + midRGB[2]*w2 + highRGB[2]*w3) / wsum + scaleMin;
00643
00644 clamp_color(rgb);
00645 }
00646
00647 void Scene::create_colorscale() {
00648 const ColorScale &scale = colorScales[scaleMethod];
00649 for (int i=0; i<MAPCLRS; i++) {
00650 float *rcol = colorData + 3*(BEGMAP + i);
00651 float relpos = float(i) / float(MAPCLRS -1);
00652 scale_color(scale.min, scale.mid, scale.max, scaleMid, relpos, scaleMin,
00653 rcol);
00654 }
00655 root.color_scale_changed();
00656 }
00657
00658 int Scene::nearest_index(float r, float g, float b) const {
00659 const float *rcol = color_value(BEGREGCLRS);
00660 float lsq = r - rcol[0]; lsq *= lsq;
00661 float tmp = g - rcol[1]; lsq += tmp * tmp;
00662 tmp = b - rcol[2]; lsq += tmp * tmp;
00663 float best = lsq;
00664 int bestidx = BEGREGCLRS;
00665 for (int n= BEGREGCLRS+1; n < (BEGREGCLRS + REGCLRS); n++) {
00666 rcol = color_value(n);
00667 lsq = r - rcol[0]; lsq *= lsq;
00668 tmp = g - rcol[1]; lsq += tmp * tmp;
00669 tmp = b - rcol[2]; lsq += tmp * tmp;
00670 if (lsq < best) {
00671 best = lsq;
00672 bestidx = n;
00673 }
00674 }
00675 return bestidx;
00676 }
00677
00678 int Scene::get_colorscale_colors(int whichScale,
00679 float min[3], float mid[3], float max[3]) {
00680 if (whichScale < 0 || whichScale >= colorScales.num())
00681 return FALSE;
00682 const ColorScale &scale = colorScales[whichScale];
00683 for (int i=0; i<3; i++) {
00684 min[i] = scale.min[i];
00685 mid[i] = scale.mid[i];
00686 max[i] = scale.max[i];
00687 }
00688 return TRUE;
00689 }
00690
00691 int Scene::set_colorscale_colors(int whichScale,
00692 const float min[3], const float mid[3], const float max[3]) {
00693 if (whichScale < 0 || whichScale >= colorScales.num())
00694 return FALSE;
00695 ColorScale &scale = colorScales[whichScale];
00696 for (int i=0; i<3; i++) {
00697 scale.min[i] = min[i];
00698 scale.mid[i] = mid[i];
00699 scale.max[i] = max[i];
00700 }
00701 create_colorscale();
00702 return TRUE;
00703 }
00704